《Java 多线程编程核心技术》笔记——第4章 Lock 的使用(一)

本文是《Java多线程编程核心技术》第四章的学习笔记,详细讲解了ReentrantLock的使用,包括使用ReentrantLock实现同步、Condition的等待/通知机制,以及公平锁和非公平锁的概念。通过多个示例演示了ReentrantLock如何实现生产者/消费者模式,展示了其在多线程控制上的灵活性。
摘要由CSDN通过智能技术生成

声明:

本博客是本人在学习《Java 多线程编程核心技术》后整理的笔记,旨在方便复习和回顾,并非用作商业用途。

本博客已标明出处,如有侵权请告知,马上删除。

本章将要介绍使用 Java5 中 Lock 对象也能实现同步的效果,而且在使用上更加方便。本章着重掌握如下 2 个知识点:

  • ReentrantLock 类的使用。
  • ReentrantReadWriteLock 类的使用。

4.1 使用 ReentrantLock 类

在 Java 多线程中,可以使用 synchronized 关键字来实现线程之间同步互斥,但在 JDK1.5 中新增加了 ReentrantLock 类也能达到同样的效果,并且在扩展功能上也更加强大,比如具有嗅探锁定、多路分支通知等功能,而且在使用上也比 synchronized 更加的灵活。

4.1.1 使用 ReentrantLock 实现同步:测试1

既然 ReentrantLock 类在功能上相比 synchronized 更多,那么就以一个初步的程序示例来介绍一下 ReentrantLock 类的使用。

  1. 创建公共类

    public class MyService {
        private Lock lock = new ReentrantLock();
    
        public void testMethod() {
            lock.lock();  //获取锁,线程就持有了“对象监视器”
            for (int i = 0; i < 3; i++) {
                System.out.println("ThreadName=" + Thread.currentThread().getName()
                        + (" " + (i + 1)));
            }
            lock.unlock();  //释放锁
        }
    }
    
  2. 创建自定义线程类

    public class MyThread extends Thread {
        private MyService myService;
    
        public MyThread(MyService myService) {
            this.myService = myService;
        }
    
        public void run() {
            myService.testMethod();
        }
    }
    
  3. 测试类

    public class Run {
        public static void main(String[] args) throws InterruptedException {
            MyService service = new MyService();
            MyThread a1 = new MyThread(service);
            MyThread a2 = new MyThread(service);
    
            a1.start();
            a2.start();
        }
    }
    

    运行结果:

    ThreadName=Thread-1 1
    ThreadName=Thread-1 2
    ThreadName=Thread-1 3
    ThreadName=Thread-0 1
    ThreadName=Thread-0 2
    ThreadName=Thread-0 3
    

从运行的结果来看,当前线程打印完毕之后将锁进行释放,其他线程才可以继续打印。线程打印的数据是分组打印,因为当前线程已经持有锁,但线程之间打印的顺序是随机的。

4.1.2 使用 ReentrantLock 实现同步:测试2

  1. 创建公共类

    public class MyService {
        private Lock lock = new ReentrantLock();
        public void methodA() {
            try {
                lock.lock();
                System.out.println("method A begin Thread name = " + Thread.currentThread().getName() + " time = " + System.currentTimeMillis());
                Thread.sleep(5000);
                System.out.println("method A   end Thread name = " + Thread.currentThread().getName() + " time = " + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    
        public void methodB() {
            try {
                lock.lock();
                System.out.println("method B begin Thread name = " + Thread.currentThread().getName() + " time = " + System.currentTimeMillis());
                Thread.sleep(5000);
                System.out.println("method B   end Thread name = " + Thread.currentThread().getName() + " time = " + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    }
    
  2. 创建 4 个自定义线程类

    public class ThreadA extends Thread {
        private MyService service;
    
        public ThreadA(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            service.methodA();
        }
    }
    
    public class ThreadAA extends Thread {
        private MyService service;
    
        public ThreadAA(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            service.methodA();
        }
    }
    
    public class ThreadB extends Thread {
        private MyService service;
    
        public ThreadB(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            service.methodB();
        }
    }
    
    public class ThreadBB extends Thread {
        private MyService service;
    
        public ThreadBB(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            service.methodB();
        }
    }
    
  3. 测试类

    public class Run {
        public static void main(String[] args) throws InterruptedException {
            MyService service = new MyService();
            ThreadA a = new ThreadA(service);
            ThreadAA aa = new ThreadAA(service);
            ThreadB b = new ThreadB(service);
            ThreadBB bb = new ThreadBB(service);
            a.setName("A");
            aa.setName("AA");
            b.setName("B");
            bb.setName("BB");
            a.start();
            aa.start();
            Thread.sleep(100);
            b.start();
            bb.start();
        }
    }
    

    运行结果:

    method A begin Thread name = AA time = 1607926082523
    method A   end Thread name = AA time = 1607926087523
    method A begin Thread name = A time = 1607926087523
    method A   end Thread name = A time = 1607926092524
    method B begin Thread name = B time = 1607926092524
    method B   end Thread name = B time = 1607926097524
    method B begin Thread name = BB time = 1607926097524
    method B   end Thread name = BB time = 1607926102524
    

此实验说明,调用 lock.lock() 代码的线程就持有了 “对象监视器”,其他线程只有等待锁被释放时再次争抢。效果和使用 synchronized 关键字一样,线程之间还是顺序执行的

4.1.3 使用 Condition 实现等待/通知:错误用法与解决

关键字 synchronized 与 wait() 和 notify()/notifyAll() 方法相结合可以实现等待/通知模式,类 ReentrantLock 也可以实现同样的功能,但需要借助于 Condition 对象。Condition 类是在 JDK5 中出现的技术,使用它有更好的灵活性,比如可以实现多路通知功能,也就是在一个 Lock 对象里面可以创建多个 Condition(即对象监视器)实例,线程对象可以注册在指定的 Condition 中,从而可以有选择性地进行线程通知,在调度线程上更加灵活。

在使用 notify()/notifyAll() 方法进行通知时,被通知的线程却是由 JVM 随机选择的。但使用 ReentrantLock 结合 Condition 类是可以实现前面介绍过的 “选择性通知”,这个功能是非常重要的,而且在 Condition 类中是默认提供的。

而 synchronized 就相当于整个 Lock 对象中只有一个单一的 Condition 对象,所有的线程都注册在它一个对象的身上。线程开始 notifyAll() 时,需要通知所有的 WAITING 线程,没有选择权,会出现相当大的效率问题。

下面来看一个示例:

  1. 创建公共类

    public class MyService {
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
    
        public void await() {
            try {
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
  2. 创建自定义线程类

    public class ThreadA extends Thread {
        private MyService service;
    
        public ThreadA(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            service.await();
        }
    }
    
  3. 测试类

    public class Run {
        public static void main(String[] args) {
            MyService service = new MyService();
            ThreadA a = new ThreadA(service);
            a.start();
        }
    }
    

    运行结果:

    Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    	at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(AbstractQueuedSynchronizer.java:1723)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2036)
    	at rt3.MyService.await(MyService.java:13)
    	at rt3.ThreadA.run(ThreadA.java:13)
    

报错的异常信息是监视器出错,解决的办法是必须在 condition.await() 方法调用之前调用 lock.lock() 代码获得同步监视器

正确使用 Condition 实现等待/通知,示例如下:

  1. 创建公共类

    public class MyService {
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
    
        public void waitMethod() {
            try {
                lock.lock();
                System.out.println("A");
                condition.await();
                System.out.println("B");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
                System.out.println("free lock!");
            }
        }
    }
    
  2. 创建自定义线程类

    public class ThreadA extends Thread {
        private MyService service;
    
        public ThreadA(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            service.waitMethod();
        }
    }
    
  3. 测试类

    public class Run {
        public static void main(String[] args) {
            MyService service = new MyService();
            ThreadA a = new ThreadA(service);
            a.start();
        }
    }
    

    运行结果:

    A
    

在控制台中只打印一个字母 A,原因是调用了 Condition 对象的 await() 方法,使当前执行任务的线程进入了等待 WAITING 状态。

4.1.4 正确使用 Condition 实现等待/通知

示例如下:

  1. 创建公共类

    public class MyService {
        private Lock lock = new ReentrantLock();
        public Condition condition = lock.newCondition();
    
        public void await() {
            try {
                lock.lock();
                System.out.println("await time = " + System.currentTimeMillis());
                condition.await();
                System.out.println("after await");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void signal() {
            try {
                lock.lock();
                System.out.println("signal time = " + System.currentTimeMillis());
                condition.signal();
            } finally {
                lock.unlock();
            }
        }
    }
    
    
  2. 创建自定义线程类

    public class ThreadA extends Thread {
        private MyService service;
    
        public ThreadA(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            service.await();
        }
    }
    
  3. 测试类

    public class Run {
        public static void main(String[] args) throws InterruptedException {
            MyService service = new MyService();
            ThreadA a = new ThreadA(service);
            a.start();
            Thread.sleep(3000);
            service.signal();
        }
    }
    

    运行结果:

    await time = 1607931307284
    signal time = 1607931310284
    after await
    

成功实现等待/通知模式。

  • Object 类中的 wait() 方法相当于 Condition 类中的 await() 方法。
  • Object 类中的 wait(Iong timeout) 方法相当于 Condition 类中的 await(long time, TimeUnit unit) 方法。
  • Object 类中的 notify() 方法相当于 Condition 类中的 signal() 方法。
  • Object 类中的 notifyAll() 方法相当于 Condition 类中的 signalAll() 方法。

4.1.5 使用多个 Condition 实现通知部分线程:错误用法

前面章节使用一个 Condition 对象来实现等待/通知模式,其实 Condition 对象也可以创建多个。那么一个 Condition 对象和多个 Condition 对象在使用上有什么区别呢?

  1. 创建公共类

    public class MyService {
        private Lock lock = new ReentrantLock();
        public Condition condition = lock.newCondition();
    
        public void awaitA() {
            try {
                lock.lock();
                System.out.println("begin awaitA time = " + System.currentTimeMillis() + " thread name = " + Thread.currentThread().getName());
                condition.await();
                System.out.println("  end awaitA time = " + System.currentTimeMillis() + " thread name = " + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void awaitB() {
            try {
                lock.lock();
                System.out.println("begin awaitB time = " + System.currentTimeMillis() + " thread name = " + Thread.currentThread().getName());
                condition.await();
                System.out.println("  end awaitA time = " + System.currentTimeMillis() + " thread name = " + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void signalAll() {
            try {
                lock.lock();
                System.out.println("signalAll time = " + System.currentTimeMillis() + " thread name = " + Thread.currentThread().getName());
                condition.signalAll();
            } finally {
                lock.unlock();
            }
        }
    }
    
  2. 创建 2 个自定义线程类

    public class ThreadA extends Thread {
        private MyService service;
    
        public ThreadA(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            service.awaitA();
        }
    }
    
    
    public class ThreadB extends Thread {
        private MyService service;
    
        public ThreadB(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            service.awaitB();
        }
    }
    
    
  3. 测试类

    public class Run {
        public static void main(String[] args) throws InterruptedException {
            /**
             * A B 线程 都会被唤醒
             */
            MyService service = new MyService();
            ThreadA a = new ThreadA(service);
            ThreadB b = new ThreadB(service);
            a.setName("A");
            b.setName("B");
            a.start();
            b.start();
            Thread.sleep(3000);
            service.signalAll();
        }
    }
    
    

    运行结果:

    begin awaitA time = 1607933192977 thread name = A
    begin awaitB time = 1607933192978 thread name = B
    signalAll time = 1607933195969 thread name = main
      end awaitA time = 1607933195969 thread name = A
      end awaitA time = 1607933195969 thread name = B
    

如果想单独唤醒部分线程该怎么处理呢?这时就有必要使用多个 Condition 对象了,也就是 Condition 对象可以唤醒部分指定线程,有助于提升程序运行的效率。可以先对线程进行分组,然后再唤醒指定组中的线程。

4.1.6 使用多个 Condition 实现通知部分线程:正确用法

  1. 创建公共类

    public class MyService {
        private Lock lock = new ReentrantLock();
        public Condition conditionA = lock.newCondition();
        public Condition conditionB = lock.newCondition();
    
        public void awaitA() {
            try {
                lock.lock();
                System.out.println("begin awaitA time = " + System.currentTimeMillis() + " thread name : " + Thread.currentThread().getName());
                conditionA.await();
                System.out.println("  end awaitA time = " + System.currentTimeMillis() + " thread name : " + Thread.currentThread().getName());
    
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
        
        public void awaitB() {
            try {
                lock.lock();
                System.out.println("begin awaitB time = " + System.currentTimeMillis() + " thread name : " + Thread.currentThread().getName());
                conditionB.await();
                System.out.println("  end awaitB time = " + System.currentTimeMillis() + " thread name : " + Thread.currentThread().getName());
    
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
        
        public void signalAll_A() {
            try {
                lock.lock();
                System.out.println("signalAll_A time = " + System.currentTimeMillis() + " thread name = " + Thread.currentThread().getName());
                conditionA.signalAll();
            }finally {
                lock.unlock();
            }
        }
        
        public void signalAll_B(){
            try {
                lock.lock();
                System.out.println("signalAll_B time = " + System.currentTimeMillis() + " thread name = " + Thread.currentThread().getName());
                conditionB.signalAll();
            }finally {
                lock.unlock();
            }
        }
    }
    
  2. 创建 2 个自定义线程类

    public class ThreadA extends Thread {
        private MyService service;
    
        public ThreadA(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            service.awaitA();
        }
    }
    
    public class ThreadB extends Thread {
       private MyService service;
    
       public ThreadB(MyService service) {
           this.service = service;
       }
    
       @Override
       public void run() {
           super.run();
           service.awaitB();
       }
    }
    
  3. 测试类

    public class Run {
        public static void main(String[] args) throws InterruptedException {
            /**
             * ReentrantLock对象可以唤醒指定种类的线程。
             * 只唤醒A
             */
            MyService service = new MyService();
            ThreadA a = new ThreadA(service);
            ThreadB b = new ThreadB(service);
            a.setName("A");
            b.setName("B");
            a.start();
            b.start();
            Thread.sleep(3000);
            service.signalAll_A();
        }
    }
    
    

    运行结果:

    begin awaitB time = 1607933799999 thread name : B
    begin awaitA time = 1607933800000 thread name : A
     signalAll_A time = 1607933802999 thread name = main
      end awaitA time = 1607933802999 thread name : A
    

程序运行后,只有线程 A 被唤醒了,线程 B 没有唤醒。

通过此实验可以得知,使用 ReentrantLock 对象可以唤醒指定种类的线程,这是控制部分线程行为的方便方式

4.1.7 实现生产者/消费者模式:一对一交替打印

  1. 创建公共类

    public class MyService {
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
        private boolean hasValue = false;
    
        public void set() {
            try {
                lock.lock();
                while (hasValue) {
                    condition.await();
                }
                System.out.println("打印★");
                hasValue = true;
                condition.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
    
        public void get() {
            try {
                lock.lock();
                while (!hasValue) {
                    condition.await();
                }
                System.out.println("打印☆");
                hasValue = false;
                condition.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    
  2. 创建 2 个自定义线程类

    public class ThreadA extends Thread {
        private MyService service;
    
        public ThreadA(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                service.set();
            }
        }
    }
    
    public class ThreadB extends Thread {
        private MyService service;
    
        public ThreadB(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                service.get();
            }
        }
    }
    
  3. 测试类

    public class Run {
        public static void main(String[] args) {
            MyService service = new MyService();
            ThreadA a = new ThreadA(service);
            ThreadB b = new ThreadB(service);
            a.start();
            b.start();
        }
    }
    

    运行结果:

    打印★
    打印☆
    打印★
    打印☆
    打印★
    打印☆
    打印★
    打印☆
    打印★
    打印☆
    打印★
    打印☆
    打印★
    打印☆
    打印★
    ...
    

通过使用 Condition 对象,成功实现交替打印的效果。

4.1.8 实现生产者/消费者模式:多对多交替打印

  1. 创建公共类

    public class MyService {
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
        private boolean hasValue = false;
    
        public void set() {
            try {
                lock.lock();
                while (hasValue) {
                    System.out.println("有可能★★连续");
                    condition.await();
                }
                System.out.println("打印★");
                hasValue = true;
                condition.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        public void get() {
            try {
                lock.lock();
                while (!hasValue) {
                    System.out.println("有可能☆☆连续");
                    condition.await();
                }
                System.out.println("打印☆");
                hasValue = false;
                condition.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    
  2. 创建 2 个自定义线程类

    public class ThreadA extends Thread {
        private MyService service;
    
        public ThreadA(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                service.set();
            }
        }
    }
    
    
    public class ThreadB extends Thread {
        private MyService service;
    
        public ThreadB(MyService service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            super.run();
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                service.get();
            }
        }
    }
    
  3. 测试类

    public class Run {
        public static void main(String[] args) {
            MyService service = new MyService();
            ThreadA[] aThread = new ThreadA[10];
            ThreadB[] bThread = new ThreadB[10];
            for (int i = 0; i < 10; i++) {
                aThread[i] = new ThreadA(service);
                bThread[i] = new ThreadB(service);
                aThread[i].start();
                bThread[i].start();
         }
        }
    }
    

    运行结果:

    ...
    打印★
    有可能★★连续
    有可能★★连续
    打印☆
    有可能☆☆连续
    有可能☆☆连续
    打印★
    有可能★★连续
    有可能★★连续
    

程序运行后又出现假死。

根据第 3 章中的 notifyAll() 解决方案,可以使用 signalAll() 方法来解决。将 MyService.java 类中两处 signal() 代码改成 signalAll() 后,程序得到正确运行,效果如下所示。

打印★
有可能★★连续
打印☆
打印★
有可能★★连续
有可能★★连续
打印☆
有可能☆☆连续
打印★
有可能★★连续
有可能★★连续
打印☆
有可能☆☆连续
...

从控制台打印的日志可以发现,运行后不再出现假死状态,假死问题被解决了。

控制台中 “打印★” 和 “打印☆” 是交替输出的,但是 “有可能★★连续” 和 “有可能☆☆连续” 却不是交替输出的,有时候出现连续打印的情况。原因是程序中使用了一个 Condition 对象,再结合 signalAll() 方法来唤醒所有的线程,那么唤醒的线程就有可能是同类,所以就出现连续打印 “有可能★★连续” 或 “有可能☆☆连续” 的情况了。

4.1.9 公平锁和非公平锁

锁 Lock 分为公平锁和非公平锁:

  • 公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的 FIFO 先进先出顺序。
  • 非公平锁就是一种获取锁的抢占机制,是随机获得锁的,和公平锁不一样的就是先来的不一定先得到锁,这个方式可能造成某些线程一直拿不到锁,结果也就是不公平的了。
  1. 公共类

    public class Service {
        private Lock lock;
    
        public Service(boolean isFair) {
            lock = new ReentrantLock(isFair);
        }
    
        public void serviceMethod() {
            try {
                lock.lock();
                System.out.println("Thread name = " + Thread.currentThread().getName() + " get locked");
            } finally {
                lock.unlock();
            }
        }
    }
    
  2. 创建公平锁测试的运行类

    public class RunFair {
        public static void main(String[] args) {
            final Service service = new Service(true);
    
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("★process " + Thread.currentThread().getName() + "run");
                    service.serviceMethod();
                }
            };
    
            Thread[] threadArray = new Thread[10];
    
            for (int i = 0; i < 10; i++) {
                threadArray[i] = new Thread(runnable);
            }
    
            for (int i = 0; i < 10; i++) {
                threadArray[i].start();
            }
        }
    }
    

    运行结果:

    ★process Thread-2run
    Thread name = Thread-2 get locked
    ★process Thread-0run
    Thread name = Thread-0 get locked
    ★process Thread-1run
    Thread name = Thread-1 get locked
    ★process Thread-3run
    Thread name = Thread-3 get locked
    ★process Thread-4run
    Thread name = Thread-4 get locked
    ★process Thread-5run
    Thread name = Thread-5 get locked
    ★process Thread-6run
    Thread name = Thread-6 get locked
    ★process Thread-8run
    Thread name = Thread-8 get locked
    ★process Thread-7run
    Thread name = Thread-7 get locked
    ★process Thread-9run
    Thread name = Thread-9 get locked
    

    打印的结果基本是呈有序的状态,这就是公平锁的特点。

  3. 创建非公平锁测试的运行类

    ublic class RunNotFair {
        public static void main(String[] args) {
            final Service service = new Service(false);
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    System.out.println("★process " + Thread.currentThread().getName() + "run");
                    service.serviceMethod();
                }
            };
    
            Thread[] threadArray = new Thread[10];
    
            for (int i = 0; i < 10; i++) {
                threadArray[i] = new Thread(runnable);
            }
    
            for (int i = 0; i < 10; i++) {
                threadArray[i].start();
            }
        }
    
    

    运行结果:

    ★process Thread-0run
    ★process Thread-2run
    ★process Thread-1run
    Thread name = Thread-0 get locked
    ★process Thread-3run
    Thread name = Thread-3 get locked
    ★process Thread-4run
    Thread name = Thread-4 get locked
    Thread name = Thread-2 get locked
    Thread name = Thread-1 get locked
    ★process Thread-5run
    Thread name = Thread-5 get locked
    ★process Thread-6run
    Thread name = Thread-6 get locked
    ★process Thread-7run
    Thread name = Thread-7 get locked
    ★process Thread-8run
    Thread name = Thread-8 get locked
    ★process Thread-9run
    Thread name = Thread-9 get locked
    

    非公平锁的运行结果基本上是乱序的,说明先 start() 启动的线程不代表先获得锁。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

bm1998

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

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

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

打赏作者

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

抵扣说明:

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

余额充值