Java并发(六)Lock锁

简介

  1. 在 Java 5.0 之前,协调共享对象的访问时可以使用的机
    制只有synchronized volatile 。Java 5.0 后增加了一些
    新的机制,但并不是一种替代内置锁的方法,而是当内
    置锁不适用时,作为一种可选择的高级功能。
  2. ReentrantLock 实现了* Lock 接口*,并提供了与
    synchronized 相同的互斥性和内存可见性。但相较于
    synchronized 提供了更高的处理锁的灵活性

注意:
是一个显示锁,lock()上锁,必须通过unlock()解锁
必须保证解锁的必须执行,通常放在finally{unlock()}中

例子

创建一个TestRunnable类实现Runnable接口,在run方法中循环打印num的值,然后num++,知道num>=5

class TestRunnable implements Runnable{

    private volatile int num = 0;

    @Override
    public void run() {

           while(num<5){
               try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           System.out.println(Thread.currentThread()+"->"+num++);
     }     
    }    
}

测试类:

public class TestLock {

    public static void main(String[] args) {
        TestRunnable tr = new TestRunnable();
        for(int i =0;i<10;i++){
            new Thread(tr).start();
        }
    }

}

输出结果:

Thread[Thread-0,5,main]->0
Thread[Thread-2,5,main]->1
Thread[Thread-9,5,main]->4
Thread[Thread-6,5,main]->5
Thread[Thread-7,5,main]->4
Thread[Thread-3,5,main]->3
Thread[Thread-5,5,main]->2
Thread[Thread-8,5,main]->8
Thread[Thread-1,5,main]->7
Thread[Thread-4,5,main]->6
Thread[Thread-0,5,main]->9

结果出现意外了,明明在run中while条件是<5,但是打印的结果却大于5

分析

以输出的结果为例,在num值为4的时候,Thread-5,Thread-6,Thread-7,Thread-8等几个线程拿到了num的值,此时他们都是4,这个时候,Thread-5的run方法打印完毕,num++为5,虽然num被volatile修饰但是因为是分为三部的,所以在Thread-6,Thread-7内部num的值变为5了,此时如果Thread-6限制性操作,就会打印出5,然后num++之后为6,这个时候Thread-7获得cpu执行权然后打印6,再次对num++操作,此时Thread-8,获得cpu执行权,然后打印num的值是7,再次对num++以此类推,导致我们看到了测试的那样的结果,这个之前的原子性有点类似。

解决方法

class TestRunnable implements Runnable{

    private volatile int num = 0;

    //创建锁
    private Lock lock = new ReentrantLock();

    @Override
    public void run() {

        lock.lock();//上锁
       try{
           while(num<5){
               try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
               System.out.println(Thread.currentThread()+"->"+num++);
           }
       }finally{
           lock.unlock();
       }

    }

}

测试结果:

Thread[Thread-0,5,main]->0
Thread[Thread-0,5,main]->1
Thread[Thread-0,5,main]->2
Thread[Thread-0,5,main]->3
Thread[Thread-0,5,main]->4
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值