JAVA中的锁——Synchronized

线程会出现的问题:同步 与 互斥

什么是同步? 什么是互斥?

Synchronized 可以作用于哪里?实现的原理?性能优化有什么?


 1.首先来说说什么是同步与互斥?

同步:线程间的通信(线程合作)

互斥:多线程并发时,某一时刻只能有一个线程访问共享资源

2.Synchronized同步处理可以作用于哪里(1)同步方法  (2)同步代码块

   (1)同步代码块锁的对象是  (this/ object及其子类 类对象 / 当前类.class)

Synchronized(锁的对象){
    //此处为代码在任意一个时刻只能有一个线程进去
}

 代码如下:

class sellTicket implements Runnable{
    private int ticket = 20000;
    @Override
    public void run() {
        while(ticket >0 ){
        synchronized (this){

                 try {
                     Thread.sleep(10);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 System.out.println(Thread.currentThread().getName()+"还剩下"+ticket--+"票");
             }
         }
    }
}

public class SynchronizedTest {
    public static void main(String[] args) {
         Runnable runnable = new sellTicket();
         Thread thread1 = new Thread(runnable,"黄牛A");
         Thread thread2 = new Thread(runnable,"黄牛B");
         thread1.start();
         thread2.start();
    }
}

(2)同步方法:直接在方法声明上使用synchronized,此时表明同步方法在任意时刻只能有一个线程进入     (默认锁的是this)

         Synchronized修饰普通方法 ,  锁当前对象this

         Synchronized修饰类的静态方法 ,  锁当前类.class

代码如下:

class sellTicket implements Runnable{
    private int ticket = 20000;
    @Override
    public void run() {
        while(ticket >0 ) {
             sell();
        }
    }
    public synchronized void sell(){
        System.out.println(Thread.currentThread().getName()+"还剩下"+ticket--+"票");
    }

}

public class SynchronizedTest {
    public static void main(String[] args) {
         Runnable runnable = new sellTicket();
         Thread thread1 = new Thread(runnable,"黄牛A");
         Thread thread2 = new Thread(runnable,"黄牛B");
         thread1.start();
         thread2.start();
    }
}

3.Synchronized实现原理

   底层实现:在使用synchronized时必须保证锁定的对象必须为object以及其子类对象

                     synchronized使用的是JVM层级别的MonitorEnter与MonitorExit实现

                    这两个指令都必须获取对象的同步监视器Monitor

4.synchronized优化

     优化让每个线程通过同步代码块时速度提高,之前synchronized获取锁失败,将线程挂起——悲观锁

优化1:CAS

           什么是CAS?    Compare And Swap(无锁操作)是一种乐观锁

         CAS中有三个参数 (O,V,N)

        O:当前线程存储的变量值     V:内存中该变量的具体值   N:希望修改的变量值

       (1)当O == V时,此时表示还没有线程修改共享变量的值,此时可以成功将内存中的值改为N

       (2)当O != V时,此时表示内存中共享变量值已被其他线程修改,此时返回内存中的最新V,再次尝试修改变量

注意:CAS产生的问题

        1.ABA问题 :比如旧值A改为了B再改为了A,刚好在做CAS检查发现旧值并没有变化,实际已经改变   

             解决方法:添加一个版本号

        2.自旋会产生大量的处理器资源

                自旋:失败重试

              解决方式:JVM尝试自旋一段时间后,若在此时间内,线程成功获取到锁,再下次获取锁时,适当延长时间,反之,适当所短时间 

       3.公平性

         处于阻塞态线程可能会一直无法获取到锁 ,  LOCK锁可以实现公平性,Synchronized无法实现公平性

优化2:锁的升级  JDK1.6后默认偏向锁

           无锁 —>偏向锁  —>轻量级锁  —> 重量级锁

    偏向锁:进去同步方法或同步代码块始终是一个线程

    轻量级锁:不同时刻有不同线程尝试获取锁

    重量级锁:同一时刻请求同一把锁,有竞争 

注意:锁只有升级过程没有降级过程

其他优化: 锁的粗化与锁消除

  锁粗化:当出现多次连续的加锁与解锁过程,会将多次加锁减锁过程粗化为一次的加锁与解锁过程

  锁消除:当对象不属于共享资源时,对象内部的同步方法或同步代码块的锁会被自动解除

 

 

 

 

          

 

           

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值