解决原子性问题,就是要解决CPU中断,但是现在CPU都是多核,因此无法保证多个CPU上的只有一个线程执行
但是在多核场景下,同一时刻,有可能有两个线程同时在执行,一个线程执行在 CPU-1 上,一个线程执行在 CPU-2 上,此时禁止 CPU 中断,只能保证 CPU 上的线程连续执行,并不能保证同一时刻只有一个线程执行,如果这两个线程同时写 long 型变量高 32 位的话,那就有可能出现我们开头提及的诡异 Bug 了。
锁要和锁的资源建立对应的关系,受保护资源和锁之间的关联关系是 N:1 的关系
为了防止自己的锁 锁了别人家的屋子
class SafeCalc {
long value = 0L;
long get() {
return value;
}
synchronized void addOne() {
value += 1;
}
}
被 synchronized 修饰后,无论是单核 CPU 还是多核 CPU,只有一个线程能够执行 addOne() 方法,所以一定能保证原子操作
课后思考
下面的代码用 synchronized 修饰代码块来尝试解决并发问题,你觉得这个使用方式正确吗?有哪些问题呢?能解决可见性和原子性问题吗?
class SafeCalc {
long value = 0L;
long get() {
synchronized (new Object()) {
return value;
}
}
void addOne() {
synchronized (new Object()) {
value += 1;
}
}
}
解答
问题
synchronized作用于对象和作用于类在底层实现上有什么不同
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1));
//任务2
pool.execute(() -> System.out.println("--helloWorld_002--" + Thread.currentThread().getName()));
}