线程 Lock 锁

线程 Lock 锁

JUC安全集合类型扩充

package com.gcbeen.thread;

import java.util.concurrent.CopyOnWriteArrayList;

// 测试JUC安全类型的集合
public class TestThreadJuc {

    public static void main(String[] args) {
        CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
        for (int k = 0; k < 3; k++) {
            new Thread(() -> {
                for (int i = 0; i < 10000; i++) {
                    list.add(Thread.currentThread().getName());
                }
            }).start();
        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }

}

CopyOnWriteArrayList 部分源码

public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    private static final long serialVersionUID = 8673264195747942595L;

    /** The lock protecting all mutators */
    final transient ReentrantLock lock = new ReentrantLock();

    /** The array, accessed only via getArray/setArray. */
    private transient volatile Object[] array;

Lock(锁)

从JDK 5.0开始, Java提供了更强大的线程同步机制一通过显式定义同步锁对象来实现同步。同步锁使用Lock对象充当。

java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。

ReentrantLock 类实现了 Lock,它拥有与 synchronized 相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是 ReentrantLock, 可以显式加锁、释放锁。

class A{
    private final Reentrantlock lock = new Reen TrantLock();
    public void m(){
        lock.lock();
        try{
            // 保证线程安全的代码
        }
        finally{
            lock.unlock();    // 如果同步代码有异常,要将unlock()写入finally语句块
        } 
    }
} 

测试Lock锁

package com.gcbeen.thread;

import java.util.concurrent.locks.ReentrantLock;

// 测试Lock锁
public class TestThreadLock {

    public static void main(String[] args) {
        TestLock testLock = new TestLock();
        new Thread(testLock).start();
        new Thread(testLock).start();
        new Thread(testLock).start();
    }

}


class TestLock implements Runnable {
    int tickerNums = 10;
    // 定义Lock锁
    private final ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            // 加锁
            try {
                lock.lock();
                if (tickerNums <= 0) {
                    break;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " : " + tickerNums--);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 解锁
                lock.unlock();
            }
        }
    }
}

// Thread-0 : 10
// Thread-0 : 9
// Thread-0 : 8
// Thread-0 : 7
// Thread-0 : 6
// Thread-0 : 5
// Thread-0 : 4
// Thread-0 : 3
// Thread-0 : 2
// Thread-0 : 1

// Process finished with exit code 0

synchroized 与 Lock 对比

  1. Lock是显式锁 (手动开启和关闭锁,别忘记关闭锁) synchronized是隐式锁, 出了作用域自动释放。

  2. Lock只有代码块锁, synchronized有代码块锁和方法锁。

  3. 使用Lock锁,JVM将花费较少的时间来调度线程, 性能更好。并且具有更好的扩展性 (提供更多的子类)。

优先使用顺序:

Lock > 同步代码块 (已经进入了方法体,分配了相应资源 ) > )>)> 同步方法 (在方法体之外)

posted @ 2022-09-30 06:26  gcbeen  阅读(46)  评论(0)    收藏  举报