JAVA锁

一、介绍

首先,java的锁分为两类:

  1. 第一类是synchronized同步关键字,这个关键字属于隐式的锁,是jyvm层面实现,使用的时候看不见;
  2. 第二类是在jdk5后增加的Lock接口以及对应的各种实现类,这属于显式的锁,就是我们能在代码层面看到锁这个对象,而这些个对象的方法实现,大都是直接依赖CPU指令的,无关jvm的实现。

在这里插入图片描述


二、synchronized

  • 如果修饰的是具体对象:锁的是对象;
  • 如果修饰的是成员方法:那锁的就是this(作用的对象是调用这个方法的对象) ;
  • 如果修饰的是静态方法:锁的就是这个对象.class

在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。

修饰一个类

class ClassName {
   public void method() {
      synchronized(ClassName.class) {
         
      }
   }
}

修饰成员方法

public class SynchronizedLockFunction implements Runnable{

    private String[] first ={"繁星积","墨染","星辰","晚霞"};
    private Integer id = 0;
    private boolean flag = true;
    public static void main(String[] args) throws InterruptedException {
        Runnable synchronizedLockFunction = new SynchronizedLockFunction();
        Thread thread = new Thread(synchronizedLockFunction);
        Thread thread1 = new Thread(synchronizedLockFunction);
        thread.start();
        thread1.start();
    }
    public synchronized void lockFunction(){
        while (flag) {
            if (id < first.length) {
                System.out.println(first[id]);
                System.out.println(Thread.currentThread().getName());
                ++id;
            } else {
                flag = false;
            }
        }
    }
    @Override
    public void run() {
        lockFunction();
    }
}

修饰一个代码块

public class SynchronizedLockCodeBlock implements Runnable{
    private boolean flag = true;
    private Integer id = 0;
    public static void main(String[] args) {
        SynchronizedLockCodeBlock synchronizedLockCodeBlock = new SynchronizedLockCodeBlock();
        Thread thread = new Thread(synchronizedLockCodeBlock);
        Thread thread1 = new Thread(synchronizedLockCodeBlock);
        thread.start();
        thread1.start();
    }
    @Override
    public void run() {
        Object o = new Object();
        while(flag) {
            synchronized (o) {
               if(id < 33){
                   System.out.println(Thread.currentThread().getName()+id);
                   id++;
               }else {
                   flag =false;
               }
            }
        }
    }
}

三、lock

Lock是一个接口,实现类常见的有:

  • 重入锁(ReentrantLock )
  • 读锁(ReadLock )
  • 写锁(writeLock )

在这里插入图片描述


一般使用ReentrantLock类做为锁。在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁 。

public class LocklivingExample implements Runnable {
    private boolean flag = true;
    private Integer id = 0;
    public static void main(String[] args) throws InterruptedException {
        LocklivingExample locklivingExample = new LocklivingExample();
        Thread thread = new Thread(locklivingExample);
        Thread thread1 = new Thread(locklivingExample);
        thread.start();
        thread1.start();
    }
    @Override
    public void run() {
        Lock reentrantLock = new ReentrantLock();
         while (flag) {
            try {
                if (reentrantLock.tryLock(3, TimeUnit.SECONDS)) {
                    if (id > 33) {
                        flag = false;
                    }
                    System.out.println(Thread.currentThread().getName() + id);
                    id++;
                }
            } catch (Exception e) {
               e.getMessage();
            }finally {
                reentrantLock.unlock();
            }
        }
    }
}

对比完了synchronized Lock 两个锁。对于java 的线程同步机制,往往还会提到的另外两个内容就是volatile 关键字和CAS 操作以及对应的原子类。 因此这里再提一下:

volatile 关键字常被称为轻量级的synchronized ,实际上这两个完全不是一个东西。我们知道了synchronized通过的是jwm层面的管程隐式的加了锁。而volatile关键字则是另一个角度,jvm也采用相应的手段,保证;

  • 被它修饰的变量的可见性:线程对变量进行修改后,要立刻写回主内存;
  • 线程对变量读取的时候,要从主内存读,而不是缓存;
  • 在它修饰变量上的操作禁止指令重排序。

    CAS是一种CPU的指令,也不屋于加锁,它通过假设没有冲突而去试探性的完成操作,如果因为冲突失败了就重试,直到成功。那么实际上我们很少直接使用CAS,但是 java里提供了一些原子变量类,就是juc包里面的各种Atomioxo类,这些类的底层实现直接使用了CAS操作来保证使用这些类型的变量的时候,操作都是原子操作,当使用他们作为共享变量的时候,也就不存在线程安全问题了。

注意: synchronized同步块执行完成或者遇到异常是锁会自动释放,而lock必须调用unlock()方法释放锁,因此在finally块中释放锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值