Java 中的锁如何使用?有什么注意事项?

Java 中常见的锁有 synchronized 可重入锁 java.util.concurrent.lock.ReentrantLock 可重复读写锁 java.util.concurrent.lock.ReentrantReadWriteLock java

 synchronized 有 3种用法编程

 修饰普通方法,执行方法代码,须要获取对象自己 this 的锁 缓存

 package constxiong.concurrency.a18; import java.util.ArrayList; import java.util.List; /** * 测试 synchronized 普通方法 * @author ConstXiong * @date 2019-09-19 10:49:46 */ public class TestSynchronizedNormalMethod { private int count = 0; // private void add1000() { private synchronized void add1000() { //使用 synchronized 修饰 add100 方法,便可得到正确的值 30000 for (int i = 0; i < 1000; i++) { count++; } } //启动 30 个线程,每一个线程 对 TestSynchronized 对象的 count 属性加 1000 private void test() throws InterruptedException { List<Thread> threads = new ArrayList<Thread>(10); for (int i = 0; i < 30; i++) { Thread t = new Thread(() -> { add1000(); }); t.start(); threads.add(t); } //等待全部线程执行完毕 for (Thread t : threads) { t.join(); } //打印 count 的值 System.out.println(count); } public static void main(String[] args) throws InterruptedException { //建立 TestSynchronizedNormalMethod 对象,调用 test 方法 new TestSynchronizedNormalMethod().test(); } }并发

  • 修饰静态方法,执行方法代码,须要获取 class 对象的锁
 package constxiong.concurrency.a18; import java.util.ArrayList; import java.util.List; /** * 测试 synchronized 静态方法 * @author ConstXiong * @date 2019-09-19 10:49:46 */ public class TestSynchronizedStaticMethod { private static int count = 0; private static void add1000() { // private synchronized static void add1000() { //使用 synchronized 修饰 add100 方法,便可得到正确的值 30000 for (int i = 0; i < 1000; i++) { count++; } } public static void main(String[] args) throws InterruptedException { //启动 30 个线程,每一个线程 对 TestSynchronized 对象的 count 属性加 1000 List<Thread> threads = new ArrayList<Thread>(10); for (int i = 0; i < 30; i++) { Thread t = new Thread(() -> { add1000(); }); t.start(); threads.add(t); } //等待全部线程执行完毕 for (Thread t : threads) { t.join(); } //打印 count 的值 System.out.println(count); } }
  • 锁定 Java 对象,修饰代码块,显示指定须要获取的 Java 对象锁
 package constxiong.concurrency.a18; import java.util.ArrayList; import java.util.List; /** * 测试 synchronized 代码块 * @author ConstXiong * @date 2019-09-19 10:49:46 */ public class TestSynchronizedCodeBlock { private int count = 0; //锁定的对象 private final Object obj = new Object(); private void add1000() { //执行下面的加 1000 的操做,都须要获取 obj 这个对象的锁 synchronized (obj) { for (int i = 0; i < 1000; i++) { count++; } } } //启动 30 个线程,每一个线程 对 TestSynchronized 对象的 count 属性加 1000 private void test() throws InterruptedException { List<Thread> threads = new ArrayList<Thread>(10); for (int i = 0; i < 30; i++) { Thread t = new Thread(() -> { add1000(); }); t.start(); threads.add(t); } //等待全部线程执行完毕 for (Thread t : threads) { t.join(); } //打印 count 的值 System.out.println(count); } public static void main(String[] args) throws InterruptedException { //建立 TestSynchronizedNormalMethod 对象,调用 test 方法 new TestSynchronizedCodeBlock().test(); } } 

可重入锁 java.util.concurrent.lock.ReentrantLock 的使用示例

 package constxiong.concurrency.a18; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * 测试 ReentrantLock * @author ConstXiong * @date 2019-09-19 11:26:50 */ public class TestReentrantLock { private int count = 0; private final Lock lock = new ReentrantLock(); private void add1000() { lock.lock(); try { for (int i = 0; i < 1000; i++) { count++; } } finally { lock.unlock(); } } //启动 30 个线程,每一个线程 对 TestSynchronized 对象的 count 属性加 1000 private void test() throws InterruptedException { List<Thread> threads = new ArrayList<Thread>(10); for (int i = 0; i < 30; i++) { Thread t = new Thread(() -> { add1000(); }); t.start(); threads.add(t); } //等待全部线程执行完毕 for (Thread t : threads) { t.join(); } //打印 count 的值 System.out.println(count); } public static void main(String[] args) throws InterruptedException { //建立 TestReentrantLock 对象,调用 test 方法 new TestReentrantLock().test(); } } dom

可重复读写锁 java.util.concurrent.lock.ReentrantReadWriteLock 的使用示例

 package constxiong.concurrency.a18; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * 测试可重入读写锁 ReentrantReadWriteLock * @author ConstXiong * @date 2019-09-19 11:36:19 */ public class TestReentrantReadWriteLock { //存储 key value 的 map private Map<String, Object> map = new HashMap<String, Object>(); //读写锁 private final ReadWriteLock lock = new ReentrantReadWriteLock(); /** * 根据 key 获取 value * @param key */ public Object get(String key) { Object value = null; lock.readLock().lock(); try { Thread.sleep(50L); value = map.get(key); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.readLock().unlock(); } return value; } /** * 设置key-value * @param key */ public void set(String key, Object value) { lock.writeLock().lock(); try { Thread.sleep(50L); map.put(key, value); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.writeLock().unlock(); } } //测试5个线程读数据,5个线程写数据 public static void main(String[] args) { //建立测试可重入读写锁 TestReentrantReadWriteLock 对象 TestReentrantReadWriteLock test = new TestReentrantReadWriteLock(); String key = "lock";//存入 map 中的 key Random r = new Random();//生成随机数做为 value for (int i = 0; i < 5; i++) { //5 个线程读 map 中 key 的 value new Thread(() -> { for (int j = 0; j < 10; j++) { System.out.println(Thread.currentThread().getName() + " read value=" + test.get(key)); } }).start(); //5 个线程写 map 中 key 的 value new Thread(() -> { for (int j = 0; j < 10; j++) { int value = r.nextInt(1000); test.set(key, value); System.out.println(Thread.currentThread().getName() + " write value=" + value); } }).start(); } } }jvm

锁的使用注意事项

synchronized 修饰代码块时,最好不要锁定基本类型的包装类,如 jvm 会缓存 -128 ~ 127 Integer 对象,每次向以下方式定义 Integer 对象,会得到同一个 Integer,若是不一样地方锁定,可能会致使诡异的性能问题或者死锁
Integer i = 100;  synchronized 修饰代码块时,要线程互斥地执行代码块,须要确保锁定的是同一个对象,这点每每在实际编程中会被忽视 synchronized 不支持尝试获取锁、锁超时和公平锁 ReentrantLock 必定要记得在 finally{} 语句块中调用 unlock() 方法释放锁,否则可能致使死锁 ReentrantLock 在并发量很高的状况,因为自旋很消耗 CPU 资源 ReentrantReadWriteLock 适合对共享资源写操做不多,读操做频繁的场景;能够从写锁降级到读锁,没法从读锁升级到写锁
相关文章
相关标签/搜索