Synchronized和Lock的实现原理与区别 附代码

导读:本篇文章讲解 Synchronized和Lock的实现原理与区别 附代码,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

用Synchronized和Lock实现交替打印奇偶数。

Synchronized

    private static void testSynchronized() {
        // 实现 synchronized 多线程交替打印奇数偶数
        Object obj = new Object();
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i <= 100; i++) {
                synchronized (obj){
                    if(i%2==1) System.out.println(Thread.currentThread().getName() + ": " +i);
                    obj.notifyAll();
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"奇数");
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i <= 100; i++) {
                synchronized (obj){
                    if(i%2==0) System.out.println(Thread.currentThread().getName() + ": " +i);
                    obj.notifyAll();
                    try {
                        obj.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"偶数");
        thread1.start();
        thread2.start();
    }

lock

public class demo2 {
    static volatile boolean flag = false;
    private static int count = 0;
    private static int timewait = 10;
    public static void main(String[] args) {
        testLock();
        // 实现 lock 多线程交替打印奇数偶数
    }
    private static void testLock() {
        ReentrantLock lock = new ReentrantLock();
        Thread thread1 = new Thread(() -> {
            while(count <= 100) {
                if(!flag) {
                    lock.lock();
                    try{
                        if(count%2==1) System.out.println(Thread.currentThread().getName() + ": " +count++);
                        flag = true;
                    }finally {
                        lock.unlock();
                    }
                }else {
                    // 防止线程空转
                    try {
                        Thread.sleep(timewait);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"奇数");


        Thread thread2 = new Thread(() -> {
            while(count <= 100) {
                if(flag) {
                    lock.lock();
                    try{
                        if(count%2==0) System.out.println(Thread.currentThread().getName() + ": " +count++);
                        flag = false;
                    }finally {
                        lock.unlock();
                    }
                }else {
                    // 防止线程空转
                    try {
                        Thread.sleep(timewait);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"偶数");
        thread1.start();
        thread2.start();
        System.out.println();
    }

}

为什么会有lock

一.synchronized的缺陷

synchronized是java中的一个关键字,也就是说是Java语言内置的特性。那么为什么会出现Lock呢?

在上面一篇文章中,我们了解到如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:

1)获取锁的线程执行完了该代码块,然后线程释放对锁的占有;

2)线程执行发生异常,此时JVM会让线程自动释放锁。

那么如果这个获取锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但是又没有释放锁,其他线程便只能干巴巴地等待,试想一下,这多么影响程序执行效率。

因此就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间或者能够响应中断),通过Lock就可以办到。

再举个例子:当有多个线程读写文件时,读操作和写操作会发生冲突现象,写操作和写操作会发生冲突现象,但是读操作和读操作不会发生冲突现象。

但是采用synchronized关键字来实现同步的话,就会导致一个问题:

如果多个线程都只是进行读操作,所以当一个线程在进行读操作时,其他线程只能等待无法进行读操作。

因此就需要一种机制来使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到。

另外,通过Lock可以知道线程有没有成功获取到锁。这个是synchronized无法办到的。

相同点 不同点

Synchronized和Lock的实现原理与区别 附代码

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/92872.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!