站点图标 度崩网-几度崩溃

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

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) 个线程写 uuidfor (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) 个线程写 uuidfor (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) 个线程写 uuidfor (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-writeprivate 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);}}@Overridepublic 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-writeprivate 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();}}@Overridepublic 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-writeprivate 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();}}@Overridepublic 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-5a9cd4de6824Thread-252 read uuid = b7fb63d7-79cc-4cc0-84ed-5a9cd4de6824Thread-251 read uuid = b7fb63d7-79cc-4cc0-84ed-5a9cd4de6824...Thread-255 read uuid = d666bfe6-dc71-4df2-882a-d530a59d7e92Thread-254 read uuid = d666bfe6-dc71-4df2-882a-d530a59d7e92Thread-253 read uuid = d666bfe6-dc71-4df2-882a-d530a59d7e92testSynchronized 耗时:22991

调用测试方法

testReentrantLock(1000);

耗时

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

调用测试方法

testReadWriteLock(1000);

耗时

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

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