并发一致性的概念?
是利用锁的机制来实现同步的,锁机制有如下两种特性:
互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个线程对需同步的代码块(复合操作)进行访问。互斥性我们也往往称为操作的原子性。
可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作从而引起不一致。
Synchronized的用法?
1.同步方法
同步非静态方法
1 /** 2 * Synchronized关键字的用法 3 * @author Administrator 4 * 5 */ 6 public class SynchronizeDemo01 { 7 8 /** 9 * 修饰非静态方法 10 * @Description: TODO 11 * @returnType: void 12 */ 13 public synchronized void accessResources1(){ 14 try { 15 TimeUnit.SECONDS.sleep(2); 16 System.out.println(Thread.currentThread().getName()+" is running!"); 17 } catch (InterruptedException e) { 18 // TODO Auto-generated catch block 19 e.printStackTrace(); 20 } 21 } 22 23 public static void main(String[] args) { 24 25 //非静态方法的测试 26 SynchronizeDemo01 demo01 = new SynchronizeDemo01(); 27 for (int i = 0; i < 5; i++) { 28 new Thread(demo01::accessResources1).start(); 29 } 30 31 } 32 33 }
同步静态方法
1 /** 2 * Synchronized关键字的用法 3 * @author Administrator 4 * 5 */ 6 public class SynchronizeDemo01 { 7 /** 8 * 修饰静态方法 9 * @Description: TODO 10 * @returnType: void 11 */ 12 public synchronized static void accessResources0(){ 13 try { 14 TimeUnit.SECONDS.sleep(2); 15 System.out.println(Thread.currentThread().getName()+" is running!"); 16 } catch (InterruptedException e) { 17 // TODO Auto-generated catch block 18 e.printStackTrace(); 19 } 20 } 21 22 public static void main(String[] args) { 23 //静态方法的测试 24 for(int i=0;i<5;i++){ 25 new Thread(SynchronizeDemo01::accessResources0).start(); 26 } 27 28 } 29 30 }
2.同步代码块
代码块对象,获取对象锁,在 Java 中,每个对象都会有一个 monitor 对象,这个对象其实就是 Java 对象的锁,通常会被称为“内置锁”或“对象锁”。类的对象可以有多个,所以每个对象有其独立的对象锁,互不干扰。
1 /** 2 * Synchronized关键字的用法 3 * @author Administrator 4 * 5 */ 6 public class SynchronizeDemo01 { 7 8 /** 9 * synchronized代码块(对象),this指的是当前对象 10 * @Description: TODO 11 * @returnType: void 12 */ 13 public void accessResources2(){ 14 synchronized(this){ 15 try { 16 TimeUnit.SECONDS.sleep(2); 17 System.out.println(Thread.currentThread().getName()+" is running!"); 18 } catch (InterruptedException e) { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 } 22 } 23 } 24 25 26 public static void main(String[] args) { 27 //非静态方法的测试 28 SynchronizeDemo01 demo01 = new SynchronizeDemo01(); 29 for (int i = 0; i < 5; i++) { 30 new Thread(demo01::accessResources2).start(); 31 } 32 33 } 34 35 }
代码块 (类.class),获取类锁,在 Java 中,针对每个类也有一个锁,可以称为“类锁”,类锁实际上是通过对象锁实现的,即类的 Class 对象锁。每个类只有一个 Class 对象,所以每个类只有一个类锁。
1 /** 2 * Synchronized关键字的用法 3 * @author Administrator 4 * 5 */ 6 public class SynchronizeDemo01 { 7 8 /** 9 * synchronized代码块(类.class) 10 * @Description: TODO 11 * @returnType: void 12 */ 13 public void accessResources3(){ 14 synchronized(SynchronizeDemo01.class){ 15 //有Class对象的所有的对象都共同使用这一个锁 16 try { 17 TimeUnit.SECONDS.sleep(2); 18 System.out.println(Thread.currentThread().getName()+" is running!"); 19 } catch (InterruptedException e) { 20 // TODO Auto-generated catch block 21 e.printStackTrace(); 22 } 23 } 24 } 25 public static void main(String[] args) { 26 //非静态方法的测试 27 SynchronizeDemo01 demo01 = new SynchronizeDemo01(); 28 for (int i = 0; i < 5; i++) { 29 new Thread(demo01::accessResources3).start(); 30 } 31 32 } 33 34 }
Java对象的monitor对象的作用?
1.当某一线程想要占有这个对象的时候,首先判断monitor 的计数器是不是0,如果是0表示还没有线程占有,这个时候线程可以占有这个对象,并且对这个对象的monitor+1;如果不为0,表示这个线程已经被其他线程占有,那么这个线程需要等待。当线程释放占有权的时候,monitor-1。
2. 同一线程可以对同一对象进行多次加锁,+1,+1,重入性
Synchronized代码块的加锁机制?
1.对代码块的加锁,通过反编译文件,发现在Monitorenter和Monitorexit中间是加锁的部分
2.对方法的加锁,通过反编译文件,发现标有ACC_SYNCHRONIZED标识的为加锁方法
Java虚拟机中几种锁的对比?
无状态锁:没有加锁
偏向锁:在对象第一次被某一线程占有的时候,会将“是否偏向锁”字段置为1,“锁标志位”记为01,写入线程号,当其他的线 程访问的时候,就会发生 竞争,如果竞争失败则升级为轻量级锁。偏向锁更加偏向第一次访问的线程获取锁成功。
轻量级锁:线程有交替适用,互斥性不是很强,当偏向锁通过CAS算法获取锁失败,把锁标志位置为00。
重量级锁:强互斥,锁标志位为10,等待时间长