锁和多线程:3种锁的使用(二)

摘要:
多线程同步锁重入锁读写锁1.同步锁2.锁接口3.ReentrantLock重入锁4.ReentrantReadWriteLock读写锁了解线程锁和多线程系列1.同步锁分为类锁和对象锁,方法锁和私有锁属于对象锁类锁:静态锁和同步锁被添加到代码中的方法,或者同步(xxx.cl)在内部使用
多线程 synchronized锁 重入锁 读写锁 

 

 

搞明白 线程多线程系列

1.synchronized锁

锁分为 类锁对象锁, 方法锁和私有锁都属于对象锁

  1. 类锁:在代码中的方法上加了staticsynchronized的锁,或者内部使用synchronized(xxx.class)

  2. 对象锁:在代码中的方法上加了synchronized的锁,或者内部使用synchronized(this)的代码段

  3. 私有锁:在类内部声明一个私有属性如private Object lock,在需要加锁的代码段synchronized(lock)

package com.lyf.lock;

/**
 * @Author lyf
 * @Date 2018/11/17 0017 14:13
 */
public class Ticket {
  private static int num = 10;
  private Object lock = new Object();

  // 类锁 static synchronized
  public static synchronized void buy01() {
    buy();
  }

  // 类锁 synchronized (xxx.class)
  public void buy02() {
    synchronized (MyLock.class){
      buy();
    }
  }

  // 对象锁 synchronized
  public synchronized void buy03() {
    buy();
  }

  // 对象锁 synchronized (this)
  public void buy04() {
    synchronized (this){
      buy();
    }
  }

  // 私有锁 synchronized (lock)
  public void buy05() {
    synchronized (lock){
      buy();
    }
  }

  public static void buy(){
    if (num > 0) {
      try {
        Thread.sleep((long) (Math.random() * 100));
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      System.out.println(Thread.currentThread().getName()+": 抢到第" + num-- + "张票...");
    } else {
      System.out.println(Thread.currentThread().getName()+": 票已售罄...");
    }
  }

  public static void main(String[] args) {
    final Ticket ticket = new Ticket();
    for (int i = 0; i < 200; i++) { 
//      new Thread(() -> { ticket.buy01(); }).start();
//      new Thread(() -> { ticket.buy02(); }).start();
//      new Thread(() -> { ticket.buy03(); }).start();
//      new Thread(() -> { ticket.buy04(); }).start();
      new Thread(() -> { ticket.buy05(); }).start();
    }
  }
}

依次放开注释,自己玩玩看吧~

synchronized加锁方式有很多弊端:

  1. A线程获得锁,B线程只能进入阻塞状态,不能取消等待.

  2. A线程进行写操作,B C 线程进行读操作.读写操作会发生冲突,读读操作也会有冲突

2.Lock接口

在concurrent包下面有一个Lock接口,接口规范中定义的方法可以解决上边synchronized所带来的问题.接口有6个实现类如下图所示:

 

锁和多线程:3种锁的使用(二)第1张
 

 

package java.util.concurrent.locks;
public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnitunit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}
  • lock 获取锁,如果其他线程获得锁,则进行等待.但需要主动释放锁unlock

  • lockInterruptibly 可中断锁,在线程等待过程中,可以调用interrupt()方法中断等待.如果已获得锁是不能被中断的.

  • tryLock 判断是否获得锁,获得返回true,否则返回false

  • tryLock(long time, TimeUnitunit) 在指定时间内判断是否获得锁

  • unlock 释放锁

  • newCondition 条件

3.ReentrantLock重入锁

ReentrantLock 是Lock的实现类,下面是使用示例:

  1. private Lock lock = new ReentrantLock();

  2. lock.lock();// 获取锁

  3. finally中调用lock.unlock();// 释放锁

package thread;

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

/**
 * @Author lyf
 * @Date 2018/11/17 0017 14:13
 */
public class MyLock {
  private static int num = 10;
  private Lock lock = new ReentrantLock();

  public void buy01() {
    lock.lock();// 获取锁
    try {
      if (num > 0) {
        Thread.sleep((long) (Math.random() * 100));
        System.out.println(Thread.currentThread().getName() + ": 抢到第" + num-- + "张票...");
      } else {
        System.out.println(Thread.currentThread().getName() + ": 票已售罄...");
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      lock.unlock();// 释放锁
    }
  }

  public static void main(String[] args) {
    final MyLock myLock = new MyLock();
    for (int i = 0; i < 200; i++) {
  	new Thread(() -> { myLock.buy01(); }, "线程"+i).start();
     }
  }
}

 

锁和多线程:3种锁的使用(二)第2张
 

 

使用lockInterruptibly获得锁,在线程等待过程中,可以被打断.

public void buy03() throws InterruptedException {
  lock.lockInterruptibly();// 获取锁
  try {
      Thread.sleep(2000);
      if (num > 0) {
        System.out.println(Thread.currentThread().getName() + ": 抢到第" + num-- + "张票...");
      } else {
        System.out.println(Thread.currentThread().getName() + ": 票已售罄...");
      }
  } finally {
    lock.unlock();// 释放锁
  }
}

Thread t1 = new Thread(()->{
  try {
    myLock.buy03();
  } catch (InterruptedException e) {
    System.out.println(Thread.currentThread().getName()+"被打断...");
  }
}, "线程1");
t1.start();// 启动线程
Thread.sleep(1000);
t1.interrupt();// 打断线程

 

锁和多线程:3种锁的使用(二)第3张
 

 

4.ReentrantReadWriteLock读写锁

读写锁可以实现:

  • 读读不冲突

  • 写写互斥

  • 读写互斥

package thread;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @Author lyf
 * @Date 2018/11/18 0018 10:30
 */
public class MyReadWriteLock {

  private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
  private int num = 0;

  public void readFile() {
    rwl.readLock().lock();
    try {
      System.out.println(Thread.currentThread().getName() + "执行读操作...");
      Thread.sleep((long) (Math.random() * 1000));
      System.out.println(Thread.currentThread().getName() + "读操作完成...");
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      rwl.readLock().unlock();
    }
  }


  public void writeFile() {
    rwl.writeLock().lock();
    System.out.println(Thread.currentThread().getName() + "执行写操作...");
    try {
      num++;
      Thread.sleep((long) (Math.random() * 1000));
      System.out.println(Thread.currentThread().getName() + "写操作完成...num: " + num);
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      rwl.writeLock().unlock();
    }
  }

  public static void main(String[] args) {

    MyReadWriteLock myReadWriteLock = new MyReadWriteLock();
    for (int i = 0; i < 5; i++) {
      new Thread(()->{myReadWriteLock.readFile();}).start();// 读语句1
      new Thread(()->{myReadWriteLock.readFile();}).start();// 读语句2
      new Thread(() -> { myReadWriteLock.writeFile(); }).start();// 写语句
    }
  }
}

单独执行读语句1:

MyReadWriteLock myReadWriteLock = new MyReadWriteLock();
for (int i = 0; i < 5; i++) {
  new Thread(()->{myReadWriteLock.readFile();}).start();// 读语句1
//   new Thread(()->{myReadWriteLock.readFile();}).start();// 读语句2
//   new Thread(() -> { myReadWriteLock.writeFile(); }).start();// 写语句
}

 

锁和多线程:3种锁的使用(二)第4张
 

 

单独执行写语句:

MyReadWriteLock myReadWriteLock = new MyReadWriteLock();
for (int i = 0; i < 5; i++) {
//      new Thread(()->{myReadWriteLock.readFile();}).start();// 读语句1
//      new Thread(()->{myReadWriteLock.readFile();}).start();// 读语句2
  new Thread(() -> { myReadWriteLock.writeFile(); }).start();// 写语句
}

 

锁和多线程:3种锁的使用(二)第5张
 

 

同时运行 读语句1 读语句2 写语句:

MyReadWriteLock myReadWriteLock = new MyReadWriteLock();
for (int i = 0; i < 5; i++) {
  new Thread(()->{myReadWriteLock.readFile();}).start();// 读语句1
  new Thread(()->{myReadWriteLock.readFile();}).start();// 读语句2
  new Thread(() -> { myReadWriteLock.writeFile(); }).start();// 写语句
}

 

锁和多线程:3种锁的使用(二)第6张
 

 

参考资料

免责声明:文章转载自《锁和多线程:3种锁的使用(二)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇有关CKEditor和CKFinder的集成JUnit —— TestSuite 的使用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

委托和多线程(一)

         定义:委托是一个类型安全的对象,它指向程序中另一个以后会被调用的方法(或多个方法)。通俗的说,委托是一个可以引用方法的对象,当创建一个委托,也就创建一个引用方法的对象,进而就可以调用那个方法,即委托可以调用它所指的方法。 委托的试用步骤: 1、定义委托:权限修饰符   delegate   返回值     委托名 (参数); 2、声明委托...

Java_如何等待子线程执行结束

工作中往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总的产景, 这时候就需要使用线程了. 一个线程启动之后, 是异步的去执行需要执行的内容的, 不会影响主线程的流程,  往往需要让主线程指定后, 等待子线程的完成. 这里有几种方式. 站在 主线程的角度, 我们可以分为主动式和被动式. 主动式指主线主动去检测某个标...

Debug技巧

多线程调试 有些时候为了观察多个线程间变量的不同状态,以及锁的获取等,就会想到在代码里加个断点debug一下。  在IDE里断点停下来的时候,可以切换到另外的线程中,跑其他的代码,不会互相影响。这里是有个开关的,在Eclipse里默认开启, 在IntelliJ IDEA里默认是没有开启的。也就是说如果你在IDEA里代码里加断点,虽然一个线程的断了下来,但其...

ACE_Task笔记

ACE_Task封装了任务,每个任务都含有一或多个线程,以及一个底层消息队列。各个任务通过这些消息队列进行通信。 其主要成员如下: open():初始化资源 close():释放资源 activate():启动线程,可指定线程的数目 svc():线程的启动位置 putq():放置消息到任务的消息队列中 getq():从任务的消息队列中取出消息 thr_co...

令牌桶、漏斗、冷启动限流在sentinel的应用

 分布式系统为了保证系统稳定性,在服务治理的限流中会根据不同场景进行限流操作,常见的限流算法有: 令牌桶:可容忍一定突发流量的速率的限流,令牌桶算法的原理是系统以恒定的速率产生令牌,然后把令牌放到令牌桶中,令牌桶有一个容量,当令牌桶满了的时候,再向其中放令牌,那么多余的令牌会被丢弃;当想要处理一个请求的时候,需要从令牌桶中取出一个令牌,如果此时令牌桶中...

【Chromium中文文档】跨进程通信 (IPC)

跨进程通信 (IPC) 转载请注明出处:https://ahangchen.gitbooks.io/chromium_doc_zh/content/zh//General_Architecture/Inter-process_Communication.html 全书地址 Chromium中文文档 for https://www.chromium.org/...