多线程编程核心技术读书笔记(二):对象及变量的并发访问(synchronized关键字)
2017-09-01 11:49
796 查看
“非线程安全”问题存在于“实例变量”中,如果是方法内的私有变量,则不存在“非线程安全”问题;
即:方法内的变量为线程安全。
实例变量为非线程安全,(因为为公用资源)
关键字synchronized取得的锁,都是对象锁,而不是对一段代码或者函数当做锁,也就是synchronized锁住的是对象;如果多线程访问的是多个对象,那JVM会创建多个锁;
共享资源的读写访问才需要同步化;
**问题:当一个线程进入一个对象的一个 synchronized 方法后,其它线程是否可进入此对象的其它方法?
1. 其他方法前是否加了 synchronized 关键字,如果没加,则能。
2. 如果这个方法内部调用了 wait,则可以进入其他 synchronized 方法。
3. 如果其他个方法都加了 synchronized 关键字,并且内部没有调用 wait,则不能。
4. 如果其他方法是 static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是 this。**
锁重入:synchronized拥有锁重入功能,即现在拥有当前锁,此时还想调用这个对象的另外的synchronize方法,是可以的,如果不可以,就会死锁;继承关系中,子类可以调用父类的同步方法;
当出现异常时,锁将自动释放;
同步不可以继承:重写函数也要加synchronized关键字
synchronized同步语句块
1、当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
2、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
3、当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
其实synchronized代码块也是获得的“对象”锁,
synchronized方法是对当前对象进行加锁,synchronized代码块是对一个对象进行加锁(synchronized(this)就是锁住当前对象;synchronized(非this对象)就是锁住这个非this对象,可以是任意对象,比如实例变量或者方法参数;synchronized(class)锁住的是这个class对象,影响class的一切实例;synchronized(static XXX)锁住的是当前类对象,因为static对象是所有类实例共有的资源;括号中的就是对象监视器,只有获取这个对象监视器才可以执行相应代码)
**静态同步synchronized方法与synchronized(class)代码块
Synchronized加到static静态方法上就是对class类上锁,影响所有该class创建的实例对这个class类中所有静态方法的调用,实现同步;不影响其实例对象对非静态方法的调用;class锁,可以对类的所有实例起作用(对static资源的调用);synchronized(class)代码块的作用和这个一样,锁住class这个类;**
数据类型String的常量池特性:在程序中str1 = “string”,与str2 = “string”实际是指向一个对象,所以在应用锁的时候synchronized(str1)与synchronized(str2)请求的是同一个锁。因此在大多数情况下,同步synchronized代码块都不使用String作为锁对象。改用其他的。
即:方法内的变量为线程安全。
实例变量为非线程安全,(因为为公用资源)
关键字synchronized取得的锁,都是对象锁,而不是对一段代码或者函数当做锁,也就是synchronized锁住的是对象;如果多线程访问的是多个对象,那JVM会创建多个锁;
共享资源的读写访问才需要同步化;
**问题:当一个线程进入一个对象的一个 synchronized 方法后,其它线程是否可进入此对象的其它方法?
1. 其他方法前是否加了 synchronized 关键字,如果没加,则能。
2. 如果这个方法内部调用了 wait,则可以进入其他 synchronized 方法。
3. 如果其他个方法都加了 synchronized 关键字,并且内部没有调用 wait,则不能。
4. 如果其他方法是 static,它用的同步锁是当前类的字节码,与非静态的方法不能同步,因为非静态的方法用的是 this。**
锁重入:synchronized拥有锁重入功能,即现在拥有当前锁,此时还想调用这个对象的另外的synchronize方法,是可以的,如果不可以,就会死锁;继承关系中,子类可以调用父类的同步方法;
当出现异常时,锁将自动释放;
同步不可以继承:重写函数也要加synchronized关键字
synchronized同步语句块
1、当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
2、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
3、当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
其实synchronized代码块也是获得的“对象”锁,
synchronized方法是对当前对象进行加锁,synchronized代码块是对一个对象进行加锁(synchronized(this)就是锁住当前对象;synchronized(非this对象)就是锁住这个非this对象,可以是任意对象,比如实例变量或者方法参数;synchronized(class)锁住的是这个class对象,影响class的一切实例;synchronized(static XXX)锁住的是当前类对象,因为static对象是所有类实例共有的资源;括号中的就是对象监视器,只有获取这个对象监视器才可以执行相应代码)
**静态同步synchronized方法与synchronized(class)代码块
Synchronized加到static静态方法上就是对class类上锁,影响所有该class创建的实例对这个class类中所有静态方法的调用,实现同步;不影响其实例对象对非静态方法的调用;class锁,可以对类的所有实例起作用(对static资源的调用);synchronized(class)代码块的作用和这个一样,锁住class这个类;**
数据类型String的常量池特性:在程序中str1 = “string”,与str2 = “string”实际是指向一个对象,所以在应用锁的时候synchronized(str1)与synchronized(str2)请求的是同一个锁。因此在大多数情况下,同步synchronized代码块都不使用String作为锁对象。改用其他的。
相关文章推荐
- 多线程编程核心技术读书笔记(二):对象及变量的并发访问(volatile关键字)
- Java多线程编程核心技术---对象及变量的并发访问(二)
- 【Java多线程编程核心技术】2.对象及变量的并发访问(下)-笔记总结
- Java多线程编程核心技术---对象及变量的并发访问(一)
- Java多线程编程核心技术---对象及变量的并发访问
- Java多线程编程核心技术(二)对象及变量的并发访问
- Java多线程编程核心技术---对象及变量的并发访问(一)
- Java多线程编程核心技术---对象及变量的并发访问(二)
- 多线程核心技术-并发访问对象&变量
- Java多线程核心技术(二):对象及变量的并发访问访问
- 《Java多线程编程核心技术》(二)对象及变量的并发访问
- java多线程之-----对象及变量的并发访问1(synchronized同步方法)
- JAVA多线程-对象及变量的并发访问(二)volatile关键字
- java多线程编程2--对象及变量的并发访问
- JAVA多线程-对象及变量的并发访问(一)synchronized详解
- 学习JAVA多线程编程 --- 《JAVA多线程编程核心技术》第2章 对象及变量的并发访问 笔记
- java多线程基础值对象和变量的并发访问之synchronized(二)
- Java 多线程并发编程之 Synchronized 关键字
- java多线程系列(二)---对象变量并发访问
- java多线程编程核心技术2-Synchronized