专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

多线程笔记 三:Lock和Condition

有了synchronized为什么还要Lock?

因为Lock和synchronized比较有如下优点

1、 尝试非阻塞地获取锁

2、 获取锁的过程可以被中断

3、 超时获取锁

Lock的标准用法

 package com.lgs;

 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;

 /**
  * lgs
  * 显示锁lock的标准写法
  */
 public class LockTemplete {

     public static void main(String[] args) {
         Lock lock = new ReentrantLock();
         //获取锁
         lock.lock();
         try{
             // do my work.....
         }finally{
             //释放锁
             lock.unlock();
         }
     }

 }

Lock的常用方法

Lock() 获取锁

tryLock尝试非阻塞地获取锁

lockInterruptibly:获取锁的过程可以被中断

tryLock(long time, TimeUnit unit) 超时获取锁

unlock()释放锁

锁的可重入

一个线程获得了锁进入了同步代码块遇到了锁仍然可以进入同步代码块

递归的时候发生锁的重入,没有锁的可重入,就会死锁

公平和非公平锁

公平锁,先对锁发出获取请求的一定先被满足。公平锁的效率比非公平锁效率要低。

为什么非公平锁的性能要高:因为非公平锁是可以插队的,如线程C被唤醒变为可执行去获取锁的过程中,线程A插队进来直接获取锁执行自己的业务,线程A执行完以后,线程C刚好唤醒完直接就获取锁运行了,这样在线程C唤醒的过程中线程A就执行完了效率更高

读写锁ReentrantReadWriteLock

##

允许多个读线程同时进行,但是只允许一个写线程(不允许其他读线程防止脏读和写线程),支持读多写少场景,性能会有提升。

 package com.lgs;

 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;

 /**
  * lgs
  * 读写锁的使用
  */
 public class RwLockTemplete {

     static final Map<String,String> map = new HashMap<>();
     static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
     static Lock r = reentrantReadWriteLock.readLock();
     static Lock w = reentrantReadWriteLock.writeLock();

     public void put(){
         w.lock();
         try{
             // do my work.....
         }finally{
             w.unlock();
         }
     }

     public void get(){
         r.lock();
         try{
             // do my work.....
         }finally{
             r.unlock();
         }
     }

 }

Condition接口有何用处?

Object的 wait,notify/notifyAll 实现等待通知机制

Condition接口和Lock配合来实现等待通知机制

Condition常用方法和使用范式

 package com.lgs;

 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;

 /**
  * lgs
  * Condition的使用方式
  */
 public class ConditionTemplete {

     Lock lock = new ReentrantLock();
     Condition condition = lock.newCondition();

     public void waitc() throws InterruptedException {
         lock.lock();
         try{
             condition.await();
         }finally{
             lock.unlock();
         }
     }

     public void waitnotify() throws InterruptedException {
         lock.lock();
         try{
             condition.signal();
             //condition.signalAll();尽量少使用
         }finally{
             lock.unlock();
         }
     }

 }

结合ReentrantLock和Condition实现线程安全的有界队列

 package com.lgs.bq;

 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.locks.Condition;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;

 /**
  * lgs
  * 结合ReentrantLock和Condition实现线程安全的有界队列
  */
 public class BlockingQueueLC<T> {
     private List queue = new LinkedList<>();
     private final int limit;
     Lock lock = new ReentrantLock();
     private Condition needNotEmpty = lock.newCondition();
     private Condition needNotFull = lock.newCondition();

     public BlockingQueueLC(int limit) {
         this.limit = limit;
     }

     public void enqueue(T item) throws InterruptedException {
         lock.lock();
         try{
             while(this.queue.size()==this.limit){
                 needNotFull.await();
             }
             this.queue.add(item);
             //通知出队线程有数据可以取了
             needNotEmpty.signal();
         }finally{
             lock.unlock();
         }
     }

     public  T dequeue() throws InterruptedException {
         lock.lock();
         try{
             while(this.queue.size()==0){
                 needNotEmpty.await();
             }
             //通知入队线程有位置可以入队了
             needNotFull.signal();
             return (T) this.queue.remove(0);
         }finally{
             lock.unlock();
         }
     }
 }
package com.lgs.bq;

/**
 * 
 */
public class BqTest {
    public static void main(String[] args) {
        BlockingQueueLC<Integer> bq = new BlockingQueueLC(10);
        Thread threadA = new ThreadPush(bq);
        threadA.setName("Push");
        Thread threadB = new ThreadPop(bq);
        threadB.setName("Pop");
        threadB.start();
        threadA.start();
    }

    private static class ThreadPush extends Thread{
        BlockingQueueLC<Integer> bq;

        public ThreadPush(BlockingQueueLC<Integer> bq) {
            this.bq = bq;
        }

        @Override
        public void run() {
            String threadName = Thread.currentThread().getName();
            int i = 5;
            while(i>0){
                try {
                    Thread.sleep(500);
                    System.out.println(" i="+i+" will push");
                    bq.enqueue(i--);
                } catch (InterruptedException e) {
                    //e.printStackTrace();
                }

            }
        }
    }

    private static class ThreadPop extends Thread{
        BlockingQueueLC<Integer> bq;

        public ThreadPop(BlockingQueueLC<Integer> bq) {
            this.bq = bq;
        }
        @Override
        public void run() {
            while(true){
                try {
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName()+" will pop.....");
                    Integer i = bq.dequeue();
                    System.out.println(" i="+i.intValue()+" alread pop");
                } catch (InterruptedException e) {
                    //e.printStackTrace();
                }
            }

        }
    }
}

来源:https://www.cnblogs.com/leeSmall/category/1143351.html

文章永久链接:https://tech.souyunku.com/14364

未经允许不得转载:搜云库技术团队 » 多线程笔记 三:Lock和Condition

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们