第二章 对象以及变量的并发访问
synchronied 对象监视器为Object时的使用,或者监视器为Class时的使用。
方法中的变量不存在非线程安全问题,永远都是线程安全的,这是方法内部的变量是私有的特性造成的。
1 synchronized的使用
在方法前加关键字synchronized即可。
1)A线程先持有object对象的Lock锁,B线程可以异步的方式调用object对象中的非synchrionized类型的方法。
2)A线程先持有object对象的Lock锁,B线程如果在这时调用了object对象中的synchrionized类型的方法则需要等待,也就是同步。
2 脏读
每个方法都加synchronized解决
3 锁重入
synchronized方法/块内部调用其他synchronized方法/块的时,是永远得到锁的。
“可重入锁”的概念是:自己可以再次获得自己的内部锁。比如有一条线程获得了某个对象的锁,此时这个对象还没有释放,当其再次想获得这个对象的锁的时候还是可以获得的,如果不可锁重入的话,就会造成死锁。
出现异常,锁就会自动释放。
同步不具有继承性,应该是发生在重写的情况下
4 synchronized同步代码块
当两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,一段时间内只能有一个线程被执行,另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块以后才能执行该代码块。
在使用同步synchronized(this)代码块时需要注意的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对同一个object中所有其他synchronized(this)同步代码块的访问被阻塞,这说明synchronized使用的“对象监视器”是一个。
关键字synchronized还可以运用在static静态方法上,如果这样写,那是对当前的*.java文件对应的Class类上锁。
从运行效果上看,并没有说明特别之处,都是同步的效果,和将sychronized关键字加到非static方法上使用的效果是一样的。而sychronized关键字加到非static静态方法上是给对象上锁。
数据类型String的常量池特性:在JVM中具有String常量池缓冲的功能,将
synchronized(String)同步块与String联合使用时,要注意带来的一些意外。一般不使用
同步方法容易造成死循环,用同步块试一下
5 内置类
public class PublicClass{
class PrivateClass{
}
}
PublicClass pubc = new PublicClass();
PrivateClass pric = pubc.new PrivateClass;
还有一种静态内置类
public class PublicClass{
static class PrivateClass{
}
}
本实验测试同步代码块sychronized(class2)对class2上锁后,其他线程只能以同步的方式调用class2中的静态方法
6 volatile 关键字
主要作用是使变量在多个线程间可见,但不支持原子性
i++问题
1)从内存中取出i的值;
2)计算i的值;
3)将i的值写到内存中。
对于用volatile修饰的变量,JVM虚拟机只是能保证从主内存中加载到线程工作内存的值是最新的,例如线程1和线程2在进行read和load的操作中,发生主内存中的count的值都是5,那么都会加载这个最新的值,也就是说volatile关键字解决的是变量读时的可见性问题,但无法保证原子性,对于多个线程访问同一个实例变量还是需要加锁同步。
使用原子类进行i++操作,除了操作时使用synchronized关键字实现同步外,还可以使用AtomicInt类进行实现。
sychronized代码块有volaite同步的功能:
` 关键字synchronized可以使用多个线程访问同一个资源具有同步性,而且它还具有将线程工作内存中的私有变量与公共内存中的变量同步的功能。