EffectiveJava2 第66条:同步访问共享的可变数据
程序员文章站
2022-07-12 18:00:30
...
保证线程安全方法 :
1, 不要跨线程访问共享变量
2, 使共享变量是 final类型的
3, 将共享可变数据的操作加上同步
当多线程共享可变数据时,每个读或者写的线程都必须执行同步。
可变数据同步方法:
1. synchronized
2. volatile 共享原子数据,非原子操作也要同步
3. ReentrantLock锁
4. Atomic类
5. 并发集合CopyOnWriteList、ConcurrentHashMap、BlockingQueue
6. concurrent框架
7. executor框架
反面案例
/**
* Broken! requires synchronization!
*/
public class SerialNumUtils {
public static volatile int serialNum = 0;
public static int getNetSerialNum() {
return serialNum++;
}
}
正确示例1
/**
* volatile synchronized
*/
public class SerialNumUtils200 {
public static volatile int serialNum = 0;
public synchronized static int getNetSerialNum() {
return serialNum++;
}
}
正确示例2
import java.util.concurrent.atomic.AtomicLong;
/**
* atomic long
*/
public class SerialNumUtils300 {
public static AtomicLong serialNum = new AtomicLong();
public static long getNetSerialNum() {
return serialNum.getAndDecrement();
}
}
特殊示例
// Broken! - How long would you expect this program to run? - Page 259
//我的虚拟机上可以正常停止,但是有些虚拟机做过优化,则不一定能正确结束
import java.util.concurrent.*;
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested) {
System.out.println(i);
i++;
}
/* 有些虚拟机优化成if(!stopRequest) while(true) i++; */
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}