并发编程-公平锁与非公平锁

并发编程之公平锁与非公平锁

前言:准备记录一下并发编程的学习,做个笔记加深印象。并发编程学习的路神的视频

目录

并发编程之公平锁与非公平锁

一、问题

二、代码示例

2.1 synchronized实现的锁

2.2 lock实现的锁

三、公平锁和非公平锁的加锁流程和区别


一、问题

是否被阻塞的线程被唤醒的顺序不为乱序就是公平锁,反之则为非公平锁?

二、代码示例

2.1 synchronized实现的锁

public class TestSysn {
    private static Logger logger = LoggerFactory.getLogger(TestSysn.class);
    /**
     * 定义一把锁
     */
    private static Object lock = new Object();

    public static void main(String[] args) throws InterruptedException {
        //线程的数量
        int N = 10;
        Thread[] threads = new Thread[N];


        for(int i = 0; i < N; ++i){
            threads[i] = new Thread(() -> {
                synchronized(lock){//t0  1.6 mutext---t0 t1....t9 到一个队列当中的去阻塞
                    logger.info(Thread.currentThread().getName() + " get synch lock!");
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            });
        }

        //main 线程可以得到锁 持有了锁
        synchronized(lock){
            for(int i = 0; i < N; ++i){
                //t0
                threads[i].start();
                Thread.sleep(200);
            }
        }
    }
}
/**
---------------------输出结果-------------------
15:17:50.974 [Thread-9] INFO com.example.thread.TestSysn - Thread-9 get synch lock!
15:17:51.181 [Thread-8] INFO com.example.thread.TestSysn - Thread-8 get synch lock!
15:17:51.384 [Thread-7] INFO com.example.thread.TestSysn - Thread-7 get synch lock!
15:17:51.585 [Thread-6] INFO com.example.thread.TestSysn - Thread-6 get synch lock!
15:17:51.789 [Thread-5] INFO com.example.thread.TestSysn - Thread-5 get synch lock!
15:17:51.992 [Thread-4] INFO com.example.thread.TestSysn - Thread-4 get synch lock!
15:17:52.198 [Thread-3] INFO com.example.thread.TestSysn - Thread-3 get synch lock!
15:17:52.401 [Thread-2] INFO com.example.thread.TestSysn - Thread-2 get synch lock!
15:17:52.605 [Thread-1] INFO com.example.thread.TestSysn - Thread-1 get synch lock!
15:17:52.811 [Thread-0] INFO com.example.thread.TestSysn - Thread-0 get synch lock!

结果分析:多次执行打印结果都是倒序打印,synchronized实现的锁,如果有多个线程阻塞,最先阻塞的最后执行,最后阻塞的最先执行。

*/

2.2 lock实现的锁

public class TestLock {
    private static Logger logger = LoggerFactory.getLogger(TestLock.class);
    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {

        int N = 10;
        Thread[] threads = new Thread[N];
        for(int i = 0; i < N; ++i){
            threads[i] = new Thread(() -> {               
                lock.lock();
                logger.info(Thread.currentThread().getName() + " lock!");
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                lock.unlock();
            });
        }
        lock.lock();
        for(int i = 0; i < N; ++i){
            threads[i].start();
            Thread.sleep(200);
        }
        lock.unlock();
    }
}
/**
---------------------输出结果-------------------
15:31:52.454 [Thread-0] INFO com.example.thread.TestLock - Thread-0 lock!
15:31:52.481 [Thread-1] INFO com.example.thread.TestLock - Thread-1 lock!
15:31:52.505 [Thread-2] INFO com.example.thread.TestLock - Thread-2 lock!
15:31:52.529 [Thread-3] INFO com.example.thread.TestLock - Thread-3 lock!
15:31:52.555 [Thread-4] INFO com.example.thread.TestLock - Thread-4 lock!
15:31:52.580 [Thread-5] INFO com.example.thread.TestLock - Thread-5 lock!
15:31:52.601 [Thread-6] INFO com.example.thread.TestLock - Thread-6 lock!
15:31:52.622 [Thread-7] INFO com.example.thread.TestLock - Thread-7 lock!
15:31:52.646 [Thread-8] INFO com.example.thread.TestLock - Thread-8 lock!
15:31:52.671 [Thread-9] INFO com.example.thread.TestLock - Thread-9 lock!

结果分析:lock实现的同步如果有多个线程阻塞,唤醒的时候是按照阻塞顺序唤醒的。
*/

总结:回答最初提出的问题,阻塞线程被唤醒的顺序是乱序还是有序并不能说明,当前锁是公平的还是非公平的。

三、公平锁和非公平锁的加锁流程和区别

分析:非公平锁在lock调用加锁的时候去抢锁(公平锁调用lock不会上来就拿锁,而是去判断队列中是否有人在排队),如果加锁失败,则去看为什么失败(是否锁被别人持有),在判断的时候如果锁没有被别人持有,非公平锁就会直接加锁(不会判断是否有人在排队),成功则执行同步代码块,失败则排队park,在进入队列后判断自己的上一个节点是否是head,如果是head则自旋一次再次抢锁,反之则真正进入排队。

公平锁:第一次加锁的时候,他不会去尝试加锁,他会去看一下我的前面队列中是否还有人在排队,如果有人在排队,自己进入队列(并不是真正的排队),然后查看自己前面的人是否为head节点,如果是则继续拿锁,成功则进入同步代码块,失败则park排队。

synchronized是非公平锁,它在抢锁过程中底层自旋调用的是pthread_spin_lock方法,当其膨胀为重量级锁时底层调用 pthread_mutex_lock方法。

总之,对于非公平锁还是公平锁,都是一朝排队,永远排队。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半路笙歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值