Java中的锁之间的区别是什么?

时间:2019-12-03 13:29:38   收藏:0   阅读:62

synchronized 和  java.util.concurrent.lock.Lock 之间的区别

 

java.util.concurrent.lock.Lock 与  java.util.concurrent.lock.ReadWriteLock 之间的区别

 

适用场景

 

synchronized、ReentrantLock、ReentrantReadWriteLock 启动 990 个线程读共享变量,10 个线程写共享变量

package constxiong.concurrency.a020;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * JDK 1.8 中锁性能的测试
 * @author ConstXiong
 */
public class TestLockPerformance {
    
    public static Object obj = new Object();//用于 synchronized 获取锁
    
    public static Lock lock = new ReentrantLock();//可重入锁
    
    public static ReadWriteLock readWriteLock = new ReentrantReadWriteLock();//读写锁
    
    public static final int READ = 0;
    
    public static final int WRITE = 1;
    
    // uuid,一个随机字符串
    public static String uuid = UUID.randomUUID().toString();

    public static void main(String[] args) throws InterruptedException {
//        testSynchronized(1000);
        
        testReentrantLock(1000);
        
//        testReadWriteLock(1000);
    }
    
    public static void testSynchronized(int threadNum) throws InterruptedException {
        long t1 = System.currentTimeMillis();
        List<Thread> tList = new ArrayList<Thread>();
        //启动 threadNum - 向上取整 (0.01 * threadNum) 个线程读 uuid, 向上取整 (0.01 * threadNum) 个线程写 uuid
        for (int i = 0; i <threadNum; i++) {
            Thread t;
            if (i % 100 == 0) {
                t = new Thread(new WorkerSynchronized(WRITE));
            } else {
                t = new Thread(new WorkerSynchronized(READ));
            }
            t.start();//启动线程
            tList.add(t);
        }
        
        for (Thread t : tList) {
            t.join();
        }
        
        long t2 = System.currentTimeMillis();
        System.out.println("testSynchronized 耗时:" + (t2 - t1));
    }
    
    public static void testReentrantLock(int threadNum) throws InterruptedException {
        long t1 = System.currentTimeMillis();
        List<Thread> tList = new ArrayList<Thread>();
        //启动 threadNum - 向上取整 (0.01 * threadNum) 个线程读 uuid, 向上取整 (0.01 * threadNum) 个线程写 uuid
        for (int i = 0; i <threadNum; i++) {
            Thread t;
            if (i % 100 == 0) {
                t = new Thread(new WorkerReentrantLock(WRITE));
            } else {
                t = new Thread(new WorkerReentrantLock(READ));
            }
            t.start();//启动线程
            tList.add(t);
        }
        
        for (Thread t : tList) {
            t.join();
        }
        
        long t2 = System.currentTimeMillis();
        System.out.println("testReentrantLock 耗时:" + (t2 - t1));
    }
    
    public static void testReadWriteLock(int threadNUm) throws InterruptedException {
        long t1 = System.currentTimeMillis();
        List<Thread> tList = new ArrayList<Thread>();
        //启动 threadNum - 向上取整 (0.01 * threadNum) 个线程读 uuid, 向上取整 (0.01 * threadNum) 个线程写 uuid
        for (int i = 0; i <threadNUm; i++) {
            Thread t;
            if (i % 100 == 0) {
                t = new Thread(new WorkerReadWriteLock(WRITE));
            } else {
                t = new Thread(new WorkerReadWriteLock(READ));
            }
            t.start();//启动线程
            tList.add(t);
        }
        
        for (Thread t : tList) {
            t.join();
        }
        
        long t2 = System.currentTimeMillis();
        System.out.println("testReadWriteLock 耗时:" + (t2 - t1));
    }
    
}

//工作线程,使用 synchronized 关键字加锁
class WorkerSynchronized implements Runnable {
    //0-read;1-write
    private int type;
    
    WorkerSynchronized(int type) {
        this.type = type;
    }
    
    //加锁读 TestLockPerformance.uuid 变量,并打印
    private void read() {
        synchronized (TestLockPerformance.obj) {
            //休眠 20 毫秒,模拟任务执行耗时
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + 
                    " read uuid = " +  TestLockPerformance.uuid);
        }
    }
    
    //加锁写 TestLockPerformance.uuid 变量,并打印
    private void write() {
        synchronized (TestLockPerformance.obj) {
            //休眠 20 毫秒,模拟任务执行耗时
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TestLockPerformance.uuid = UUID.randomUUID().toString();
            System.out.println(Thread.currentThread().getName() + 
                    " write uuid = " +  TestLockPerformance.uuid);
        }
    }
    
    @Override
    public void run() {
        //type = 0,线程读 TestLockPerformance.uuid 变量
        if (type == 0) {
            read();
        //type = 1,线程生成 uuid,写入 TestLockPerformance.uuid 变量
        } else {
            write();
        }
    }
}

//工作线程,使用 ReentrantLock 加锁
class WorkerReentrantLock implements Runnable {
    //0-read;1-write
    private int type;
    
    WorkerReentrantLock(int type) {
        this.type = type;
    }
    
    //加锁读 TestLockPerformance.uuid 变量,并打印
    private void read() {
        TestLockPerformance.lock.lock();
        try {
            //休眠 20 毫秒,模拟任务执行耗时
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + 
                    " read uuid = " +  TestLockPerformance.uuid);
        } finally {
            TestLockPerformance.lock.unlock();
        }
        
    }
    
    //加锁写 TestLockPerformance.uuid 变量,并打印
    private void write() {
        TestLockPerformance.lock.lock();
        try {
            //休眠 20 毫秒,模拟任务执行耗时
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TestLockPerformance.uuid = UUID.randomUUID().toString();
            System.out.println(Thread.currentThread().getName() + 
                    " write uuid = " +  TestLockPerformance.uuid);
        } finally {
            TestLockPerformance.lock.unlock();
        }
    }
    
    @Override
    public void run() {
        //type = 0,线程读 TestLockPerformance.uuid 变量
        if (type == 0) {
            read();
        //type = 1,线程生成 uuid,写入 TestLockPerformance.uuid 变量
        } else {
            write();
        }
    }
}


//工作线程,使用 ReentrantReadWriteLock 关键字加锁
class WorkerReadWriteLock implements Runnable {
    //0-read;1-write
    private int type;
    
    WorkerReadWriteLock(int type) {
        this.type = type;
    }
    
    //加锁读 TestLockPerformance.uuid 变量,并打印
    private void read() {
        TestLockPerformance.readWriteLock.readLock().lock();
        try {
            //休眠 20 毫秒,模拟任务执行耗时
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + 
                    " read uuid = " +  TestLockPerformance.uuid);
        } finally {
            TestLockPerformance.readWriteLock.readLock().unlock();
        }
    }
    
    //加锁写 TestLockPerformance.uuid 变量,并打印
    private void write() {
        TestLockPerformance.readWriteLock.writeLock().lock();
        try {
            //休眠 20 毫秒,模拟任务执行耗时
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TestLockPerformance.uuid = UUID.randomUUID().toString();
            System.out.println(Thread.currentThread().getName() + 
                    " write uuid = " +  TestLockPerformance.uuid);
        } finally {
            TestLockPerformance.readWriteLock.writeLock().unlock();
        }
    }
    
    @Override
    public void run() {
        //type = 0,线程读 TestLockPerformance.uuid 变量
        if (type == 0) {
            read();
        //type = 1,线程生成 uuid,写入 TestLockPerformance.uuid 变量
        } else {
            write();
        }
    }
}

 

 

调用测试方法 

testSynchronized(1000);

耗时

Thread-0 write uuid = b7fb63d7-79cc-4cc0-84ed-5a9cd4de6824
Thread-252 read uuid = b7fb63d7-79cc-4cc0-84ed-5a9cd4de6824
Thread-251 read uuid = b7fb63d7-79cc-4cc0-84ed-5a9cd4de6824
.
.
.
Thread-255 read uuid = d666bfe6-dc71-4df2-882a-d530a59d7e92
Thread-254 read uuid = d666bfe6-dc71-4df2-882a-d530a59d7e92
Thread-253 read uuid = d666bfe6-dc71-4df2-882a-d530a59d7e92
testSynchronized 耗时:22991

 

调用测试方法 

testReentrantLock(1000);

耗时

Thread-0 write uuid = 4352eb13-d284-47ec-8caa-fc81d91d08e1
Thread-1 read uuid = 4352eb13-d284-47ec-8caa-fc81d91d08e1
Thread-485 read uuid = 4352eb13-d284-47ec-8caa-fc81d91d08e1
.
.
.
Thread-997 read uuid = 9d7f0a78-5eb7-4506-9e98-e8e9a7a717a5
Thread-998 read uuid = 9d7f0a78-5eb7-4506-9e98-e8e9a7a717a5
Thread-999 read uuid = 9d7f0a78-5eb7-4506-9e98-e8e9a7a717a5
testReentrantLock 耗时:22935

 

调用测试方法 

testReadWriteLock(1000);

耗时

Thread-0 write uuid = 81c13f80-fb19-4b27-9d21-2e99f8c8acbd
Thread-277 read uuid = 81c13f80-fb19-4b27-9d21-2e99f8c8acbd
Thread-278 read uuid = 81c13f80-fb19-4b27-9d21-2e99f8c8acbd
.
.
.
Thread-975 read uuid = 35be0359-1973-4a4f-85b7-918053d841f7
Thread-971 read uuid = 35be0359-1973-4a4f-85b7-918053d841f7
Thread-964 read uuid = 35be0359-1973-4a4f-85b7-918053d841f7
testReadWriteLock 耗时:543

 

通过耗时测试可以看出,使用 synchronized 和 ReentrantLock 耗时相近;但是由于 990 个线程读,10 个线程写,使用 ReentrantReadWriteLock 耗时 543 毫秒。


 


技术分享图片

 

所有资源资源汇总于公众号

技术分享图片

 

 

原文:https://www.cnblogs.com/ConstXiong/p/11976056.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!