知识点
并发的几种级别、创建线程的几种方式、线程基本操作和线程协作。线程同步的几种方式、
Java各种锁:
悲观乐观、自旋、偏向、轻量级、重量级、读锁、写锁、读写锁、 可重入/不可重入锁、公平非公平锁
ReenTrantLock和Syncronized锁的异同点
volatile和Syncronized关键字的异同点
Syncronized相关问题:
锁定同步代码块:synchronized(this) {
for (int i = 0; i < 5; i++)
...........
这种形式锁定代码块,锁得就是当前对象
当两个并发线程(thread1和thread2)访问同一个对象中的synchronized(this)代码块时,
只有一个获取到该锁的线程能够执行,其它所有需要访问synchronized(this) 锁定的同步代码块的线程都被阻塞,
除非通过条件判断,一个线程走synchronized(this) 锁定的同步代码块,一个不走synchronized(this) 锁定的同步代码块,那么这两个线程可以同时执行。
但是,尤其关键的是,当一个线程访问该实例对象object的一个synchronized(this)同步代码块时
,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
或者:
String s="1";
synchronized (s) {
System.out.println("showC..");
}
这种情况下锁的是字符串s
那么其他线程对object中其它 synchronized( 除了s的其他东西 ) 锁定的同步代码块的访问不会被阻塞。
锁定方法:
直接锁定当前实例对象this,只有一个获取到该锁的线程能够执行,其它所有需要访问synchronized(this) 锁定的同步代码块的线程都被阻塞,
其它所有需要访问锁定的同步方法的线程也都被阻塞,
除非通过条件判断,一个线程走synchronized(this) 锁定的同步代码块,一个不走synchronized(this) 锁定的同步代码块,那么这两个线程可以同时执行。
锁定静态方法:
静态方法是属于类的而不属于对象的。synchronized修饰的静态方法锁定的是这个类的所有对象。
锁定类(class):
synchronized修饰的静态方法锁定的是这个类的所有对象。
其他注意事项:
虽然说在java中一切皆对象, 但是锁必须是引用类型的(例如字符串s),基本数据类型则不可以 。每一个引用类型的对象都可以隐式的扮演一个用于同步的锁的角色,
执行线程进入synchronized块之前会自动获得锁,无论是通过正常语句退出还是执行过程中抛出了异常,线程都会在放弃对synchronized块的控制时自动释放锁。
对共享资源的访问必须是顺序的,也就是说当多个线程对共享资源访问的时候,只能有一个线程可以获得该共享资源的锁,当线程A尝试获取线程B的锁时,
线程A必须等待或者阻塞,直到线程B释放该锁为止,否则线程A将一直等待下去,因此java内置锁也称作互斥锁,也即是说锁实际上是一种互斥机制。
synchronized具有锁重入功能,当一个线程已经持有一个对象锁后,
再次请求该对象锁时是可以得到该对象的锁的,这种方式是必须的,否则在一个synchronized方法内部就没有办法调用该对象的另外一个synchronized方法了。
锁重入是通过为每个所关联一个计数器和一个占有它的线程,当计数器为0时,认为锁是未被占有的。线程请求一个未被占有的锁时,JVM会记录锁的占有者,
并将计数器设置为1。如果同一个线程再次请求该锁,计数器会递增,每次占有的线程退出同步代码块时计数器会递减,直至减为0时锁才会被释放
在声明一个对象作为锁的时候要注意字符串类型锁对象,因为字符串有一个常量池,如果不同的线程持有的锁是具有相同字符的字符串锁时,两个锁实际上同一个锁。
一些实例
一些实例