2020年10月29日星期四

juc的锁

Synchronized

  1. 概念:
    重量级锁、重入锁、jvm 级别锁
    使用:方法:ACC_SYNCHRONIZED、代码块 monitorenter\monitorexit
    jvm 监视器
  2. 范围:方法和代码块(对象锁和类锁):
  • 对于普通同步方法,锁是当前实例对象。 对于静态同步方法,锁是当前类的 Class 对象。 对于同步方法块,锁是 Synchonized
    括号里配置的对象。
  1. 场景:

资源竞争

  1. Lock&ReentrantLock 写法:
try { lock.lock();} finally { lock.unlock();}
  • void lock() 获取锁,调用该方法当前线程将会获取锁,当锁获取后,该方法将返回。
  • void lockInterruptibly() throws InterruptedException 可中断获取锁,与 lock()方法不同之处在于该方
  • 法会响应中断,即在锁的获取过程中可以中断当前线程
  • boolean tryLock() 尝试非阻塞的获取锁,调用该方法立即返回,true 表示获取到锁
  • boolean tryLock(long time,TimeUnit unit) throws InterruptedException 超时获取锁,以下情况会返回:
  • 时间内获取到了锁,时间内被中断,时间到了没有获取到锁。
  • void unlock() 释放锁
  1. 统计:
    java.util.concurrent.locks.ReentrantLock#getHoldCount
    java.util.concurrent.locks.ReentrantLock#getQueuedThreads

  2. Synchronized 和 ReentrantLock 对比:

  • Synchronized:jvm 层级的锁 自动加锁自动释放锁
  • Lock:依赖特殊的 cpu 指令,代码实现、手动加锁和释放锁、Condition(生产消费模式)
  • ReentrantReadWriteLock 读写锁
  • 细粒度问题 ,读是共享的、写是独占的
  • java8 增加了对读写锁的优化:StampedLock
  1. 实例代码
  • static Lock可以锁注当前类 非静态的只能锁住当前类的实例对象
package com.itcode.锁;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * @author 夏天 * @date 2020年10月29日 22:32 */public class ReentrantLock01 implements Runnable { private static int i = 0; static Lock lock = new ReentrantLock(); private void add() {  lock.lock();  try {   for (int i1 = 0; i1 < 5000; i1++) {    i++;   }  } finally {   lock.unlock();  } } @Override public void run() {  add(); } public static void main(String[] args) throws InterruptedException {  for (int j = 0; j < 20; j++) {   i = 0;   ReentrantLock01 sync01 = new ReentrantLock01();   ReentrantLock01 sync02 = new ReentrantLock01();   Thread t1 = new Thread(sync01);   Thread t2 = new Thread(sync02);   t1.start();   t2.start();   t1.join();   t2.join();   System.out.println(i);  } }}

Lock之tryLock

使用方法:

try {	if(lock.tryLock());} finally {	//获取到锁在释放 如果不加条件判断 获取不到锁也会进行释放 会抛出异常IllegalMonitorStateException	if (lock.isHeldByCurrentThread()) {		lock.unlock();	}}
  1. tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。
  1. boolean tryLock(long timeout, TimeUnit unit) :
    参数1 等待时间,参数2 时间单位
    等待指定时间如果还获取不到锁返回false

实例代码:

package com.itcode.锁;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * @author 夏天 * @date 2020年10月29日 22:32 */public class ReentrantLock02 implements Runnable { private static int i = 0; ReentrantLock lock = new ReentrantLock(); @Override public void run() {  try {   if (lock.tryLock(4, TimeUnit.SECONDS)) {    System.out.println(Thread.currentThread().getName() + "获取");    Thread.sleep(6000);   } else {    System.out.println(Thread.currentThread().getName() + "获取锁失败");   }  } catch (InterruptedException e) {   e.printStackTrace();  } finally {   //注意 不加这个会报错 IllegalMonitorStateException 没有锁无法解锁   if (lock.isHeldByCurrentThread()) {    lock.unlock();   }  } } public static void main(String[] args) throws InterruptedException {  ReentrantLock02 reentrantLock02 = new ReentrantLock02();  Thread t1 = new Thread(reentrantLock02);  Thread t2 = new Thread(reentrantLock02);  t1.start();  t2.start();  t1.join();  t2.join(); }}

ReentrantReadWriteLock 读写锁

细粒度问题 ,读是共享的、写是独占的

package com.itcode.锁;import java.util.concurrent.*;import java.util.concurrent.locks.ReentrantReadWriteLock;/** * @author 夏天 * @date 2020年10月29日 22:42 * 可以同时读 上了写锁后就不可以读了 */public class ReadWriterLockTest { ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock(); ReentrantReadWriteLock.ReadLock readLock = lock.readLock(); public String query() {  readLock.lock();  try {   Thread.sleep(50);   System.out.println("读数据");   return "成功";  } catch (InterruptedException e) {   e.printStackTrace();   return "成功";  } finally {   readLock.unlock();  } } public void save() {  writeLock.lock();  try {   System.out.println("保存数据");   Thread.sleep(2000);  } catch (InterruptedException e) {   e.printStackTrace();  } finally {   writeLock.unlock();  } } /**  * 读50次  */ int readCount = 50; /**  * 写5次  */ int writeCount = 5; public static void main(String[] args) throws InterruptedException, ExecutionException {  ReadWriterLockTest readWriterLockTest = new ReadWriterLockTest();  //new Thread(() -> {  // while (true) {  //  readWriterLockTest.query();  // }  //}).start();  //new Thread(() -> {  // while (true) {  //  try {  //   readWriterLockTest.save();  //  } catch (InterruptedException e) {  //   e.printStackTrace();  //  }  // }  //}).start();  CompletableFuture<String> queryFuture = CompletableFuture.supplyAsync(() -> {   while (readWriterLockTest.readCount-- > 0) {    readWriterLockTest.query();   }   return "查询完成";  });  CompletableFuture<String> saveFuture = CompletableFuture.supplyAsync(() -> {   while (readWriterLockTest.writeCount-- > 0) {    readWriterLockTest.save();   }   return "保存完成";  });  //等待所有线程结束 无法接受返回值 ,接收返回值使用anyOf  CompletableFuture.allOf(queryFuture, saveFuture).get(); }}

原文转载:http://www.shaoqun.com/a/484780.html

eori:https://www.ikjzd.com/w/499

灰色清关:https://www.ikjzd.com/w/1409

bsci:https://www.ikjzd.com/w/2339


Synchronized概念:重量级锁、重入锁、jvm级别锁使用:方法:ACC_SYNCHRONIZED、代码块monitorenter\monitorexitjvm监视器范围:方法和代码块(对象锁和类锁):对于普通同步方法,锁是当前实例对象。对于静态同步方法,锁是当前类的Class对象。对于同步方法块,锁是Synchonized括号里配置的对象。场景:资源竞争Lock&Reentrant
腾邦:https://www.ikjzd.com/w/1382
美菜网:https://www.ikjzd.com/w/1874
2020广州万圣节晚上什么地方最刺激?万圣节广州夜场好玩活:http://tour.shaoqun.com/a/69544.html
亚马逊 Q&A 这么刷:https://www.ikjzd.com/home/5306
9月贸易新规来了!你一定不知道的一些重点!:https://www.ikjzd.com/home/128989

没有评论:

发表评论