java线程同步是什么意思,java线程同步的几种方法

  java线程同步是什么意思,java线程同步的几种方法

  

  如何解决写爬虫IP受阻的问题?立即使用。

  线程同步

  当同一个对象被多个线程调用时,为了安全准确地运行,需要对对象进行同步,以保证每个线程使用时对象的结果正确,对象的状态合理。这部分涉及到同步、线程锁等知识点。这部分只涉及同步和同步锁的概念。

  synchronized

  同步关键字可以修改对象和方法,通常如下使用:

  //同步代码块

  同步(对象对象){

  .

  }

  //或者

  //同步方法

  公共同步void测试(){

  .

  }有一个同步监视器的概念。例如,上述同步代码块的object对象和synchronized方法的this对象将同步监视。当多个线程同时调用一个同步的代码块或方法时,任何时候都只有一个线程可以获取同步的被监控对象的锁,代码执行后锁会被释放。在此期间,其他调用线程只能在锁释放后调用。

  文中提到的SellRunnable类中的sell方法也使用了synchronized方法。上面文章中的代码执行速度太快,所以无法感知。修改一下就能明白有没有同步差异。

  公共类ThreadTest {

  公共静态void main(String[] args) {

  sell runnable sell runnable=new sell runnable();

  Thread thread1=新线程(sellRunnable, 1 );

  Thread thread2=新线程(sellRunnable, 2 );

  Thread thread3=新线程(sellRunnable, 3 );

  thread 2 . start();

  thread 1 . start();

  thread 3 . start();

  }

  }

  类SellRunnable实现Runnable {

  //有十张票。

  int index=10

  public void sell() {

  if (index=1) {

  尝试{

  thread . sleep(1000);

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  索引-;

  System.out.println(销售窗口: Thread.currentThread()。getName()

  卖出一张票,剩下的:

  指数);

  }否则{

  System.out.println(销售窗口: Thread.currentThread()。getName()‘买的时候没票’);

  }

  }

  @覆盖

  公共无效运行(){

  while(索引0) {

  System.out.println(销售窗口: Thread.currentThread()。getName()开始买票);

  sell();

  }

  }

  }

  //执行结果:

  销售窗口:1开始买票。

  售票窗口:开始买票。

  售票窗口:3点开始买票。

  销售窗口:售出一张票,剩余9张

  售票窗口:开始买票。

  销售窗口:售出1张票,剩余9张

  销售窗口:1开始买票。

  销售窗口:售出3张票,剩余8张

  售票窗口:3点开始买票。

  销售窗口:1售出一张票,其余:6

  销售窗口:1开始买票。

  销售窗口:售出一张票,剩余6张

  售票窗口:开始买票。

  销售窗口:售出3张票,剩余5张

  售票窗口:3点开始买票。

  销售窗口:1卖出了一张票,剩下的:4

  销售窗口:1开始买票。

  销售窗口:售出一张票,剩余3张

  销售窗口:售出一张票,剩余2

  售票窗口:3点开始买票。

  售票窗口:开始买票。

  销售窗口:售出3张票,剩余1张

  销售窗口:2售出一张票,剩余:0

  销售窗口:1卖出一张票,其余:1

  过程结束,退出代码为0 //如您所见,减少投票数是错误的。

  //sell方法在添加synchronized修饰符后执行结果:

  公共同步void sell() {

  if (index=1) {

  尝试{

  thread . sleep(1000);

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  索引-;

  System.out.println(销售窗口: Thread.currentThread()。getName()

  卖出一张票,剩下的:

  指数);

  }否则{

  System.out.println(销售窗口: Thread.currentThread()。getName()‘买的时候没票’);

  }

  }

  售票窗口:开始买票。

  售票窗口:3点开始买票。

  销售窗口:1开始买票。

  销售窗口:售出一张票,剩余9张

  售票窗口:开始买票。

  销售窗口:1卖出一张票,其余:8

  销售窗口:1开始买票。

  销售窗口:售出一张票,剩余7张

  售票窗口:3点开始买票。

  销售窗口:1售出一张票,其余:6

  销售窗口:1开始买票。

  销售窗口:售出一张票,剩余5张

  售票窗口:开始买票。

  销售窗口:1卖出了一张票,剩下的:4

  销售窗口:1开始买票。

  销售窗口:1卖出一张票,其余:3

  销售窗口:1开始买票。

  销售窗口:售出一张票,剩余2

  售票窗口:3点开始买票。

  销售窗口:1卖出一张票,其余:1

  销售窗口:1开始买票。

  销售窗口:1售出一张票,剩余:0

  销售窗口:买的时候没有票。

  销售窗口:3买的时候没有票。

  过程结束,退出代码为0 //如您所见,投票数正常减少。同步sell方法后,在某个时刻,只有一个线程会调用该方法,所以在内部判断索引时得到的结果就是正确的结果。

  在上述同步过程中,为了保证线程安全,降低了运行效率。为此,不要在线程使用类中同步标识不必要的方法和对象,只标识竞争的资源或代码。

  经过鉴定,有以下几点可以开锁:

  代码和方法的执行完成(正常完成、返回或中断、抛出异常)

  调用了wait方法,导致当前线程暂停。

  当线程执行到同步代码块时,sleep和yield方法不会释放同步锁,suspend方法也不会(尽量避免在线程操作过程中使用suspend和resume来操作线程状态,容易导致死锁。)

  同步锁Lock

  文中提到的synchronized是java中的一个关键词。还提到线程在睡眠或IO操作时不会释放线程锁,其他线程要一直等待,有时会降低执行的效率。因此,需要一种在线程被阻塞时可以释放线程锁的替代方案。Lock的出现解决了这个问题。

  Lock是java中的一个类。在java.util.concurrent.locks包中,具体代码如下:

  公共接口锁{

  void lock();//锁定

  void lockInterruptibly()引发InterruptedException//锁定

  布尔tryLock();//锁定

  布尔tryLock(long time,TimeUnit单位)抛出InterruptedException//锁定

  void unlock();//释放锁定

  condition new condition();//用于线程协作

  lock接口的一个实现子类是ReentrantLock。在java.util.concurrent.locks包下,ReentrantLock的源代码如下:

  公共类ReentrantLock实现锁,Serializable {

  private static final long serial version uid=7373984872572414699 l;

  private final ReentrantLock。Sync同步;

  public ReentrantLock() {

  this.sync=new ReentrantLock。NonfairSync();

  }

  public reentrant lock(boolean var 1){//创建一个公平锁?

  this.sync=(ReentrantLock。Sync)(var1?新的ReentrantLock。FairSync():新的ReentrantLock。

  NonfairSync());

  }

  公共void锁(){

  this . sync . lock();

  }

  public void lockInterruptibly()抛出InterruptedException {

  this . sync . acquire interruptible(1);

  }

  公共布尔tryLock() {

  返回this . sync . nonfairtryacquire(1);

  }

  public boolean tryLock(long var1,TimeUnit var3)抛出InterruptedException {

  返回this.sync.tryAcquireNanos(1,var 3 . tonanos(var 1));

  }

  公共void解锁(){

  this . sync . release(1);

  }

  公共条件newCondition() {

  返回this . sync . new condition();

  }

  public gethold count(){//当前线程持有的锁的数量

  返回this . sync . getholdcount();

  }

  public boolean isheldbycurrentThread(){//当前线程是否持有锁

  返回this . sync . isheldexclusive();

  }

  Public boolean isLocked() {//锁是否被另一个线程持有?

  返回this . sync . is locked();

  }

  public final boolean is fair(){///是公平锁吗?

  返回ReentrantLock的this.sync实例。FairSync

  }

  受保护线程getOwner() {//持有当前锁的线程

  返回this . sync . get owner();

  }

  public boolean hasqueuedthreads(){//是否有线程在等待锁?

  返回this . sync . hasqueuedthreads();

  }

  public boolean hasqueuedthread(thread var 1){//目标线程是否在等待锁?

  返回this . sync . is queued(var 1);

  }

  public int getqueuelength(){//等待此锁的线程数

  返回this . sync . getqueuelength();

  }

  受保护的集合线程GetQueuedThreads(){//获取等待此锁的所有线程的集合。

  返回this . sync . getqueuedthreads();

  }

  .

  }Lock的使用方法

  锁

  Lock()用于获取锁,如果锁被其他线程占用,就会进入等待。

  公共类锁定测试{

  公共静态void main(String[] args) {

  com . test . Java . sell runnable sell runnable=new com . test . Java . sell runnable();

  ThreadThread1=新线程(sellrunnable, window 1 );

  ThreadThread2=新线程(sellrunnable, window 2 );

  ThreadThread3=新线程(sellrunnable, window 3 );

  thread 1 . start();

  thread 2 . start();

  thread 3 . start();

  }

  }公共类SellRunnable实现Runnable {

  //有十张票。

  int index=10

  lock lock=new reentrant lock();

  public void sell() {

  尝试{

  lock . lock();

  System.out.println(销售计数器: Thread.currentThread()。getName()

  获取票源’);

  if (index=1) {

  索引-;

  System.out.println(销售计数器: Thread.currentThread()。getName()

  卖出一张票,剩下的:

  指数);

  }否则{

  System.out.println(销售计数器: Thread.currentThread()。getName()

  买票的时候000);

  }

  }最后{

  lock . unlock();

  }

  }

  @覆盖

  公共无效运行(){

  while(索引0) {

  尝试{

  thread . sleep(100);

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  sell();

  }

  }

  }运行结果:

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口售出一张票,剩余的9张

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口卖了一张票,剩余8张。

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口售出一张票,剩余7张

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余6张

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口售出一张票,剩余5张

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口售出一张票,剩余数量为4张。

  销售柜台:3号窗口有票源。

  销售柜台:一张票在3号窗口售出,剩下的是3张

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余的2

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口卖了一张票,剩下一张是1。

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口售出一张票,剩余:0

  销售柜台:1号窗口有票源。

  销售柜台:1000号窗口没有票。

  销售柜台:2号窗口有票源。

  销售柜台:2000号窗口没有票。

  进程结束,退出代码为0 //每个窗口随机获取票源,然后出售车票tryLock。

  TryLock()尝试获取锁,成功则返回true,失败则返回false,因此不会进入等待状态。

  公共类SellRunnable实现Runnable {

  //有十张票。

  int index=10

  lock lock=new reentrant lock();

  public void sell() {

  if (lock.tryLock()) {

  尝试{

  System.out.println(销售计数器: Thread.currentThread()。getName()

  获取票源’);

  if (index=1) {

  索引-;

  System.out.println(销售计数器: Thread.currentThread()。getName()

  卖了一张票,剩下的:‘指数);

  }否则{

  System.out.println(销售计数器: Thread.currentThread()。getName()

  买票的时候000);

  }

  }最后{

  lock . unlock();

  }

  }否则{

  System.out.println(销售计数器: Thread.currentThread()。 getName()未获得票证来源!);

  }

  }

  @覆盖

  公共无效运行(){

  while(索引0) {

  尝试{

  thread . sleep(100);

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  sell();

  }

  }

  }运行结果:

  销售柜台:1号窗口有票源。

  销售柜台:3号窗口没有获得票源!

  销售柜台:2号窗口没有获得票源!

  销售柜台:1号窗口售出一张票,剩余9张

  销售柜台:2号窗口没有获得票源!

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口卖了一张票,剩余8张。

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余7张

  销售柜台:1号窗口没有获得票源!

  销售柜台:3号窗口没有获得票源!

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口售出一张票,剩余6张

  销售柜台:1号窗口有票源。

  销售柜台:2号窗口没有获得票源!

  销售柜台:3号窗口没有获得票源!

  销售柜台:1号窗口售出一张票,剩余5张

  销售柜台:2号窗口有票源。

  销售柜台:1号窗口没有获得票源!

  销售柜台:2号窗口售出一张票,剩余数量为4张。

  销售柜台:3号窗口没有获得票源!

  销售柜台:1号窗口有票源。

  销售柜台:2号窗口没有获得票源!

  销售柜台:3号窗口没有获得票源!

  销售柜台:1号窗口售出一张票,剩余的3张

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余的2

  销售柜台:2号窗口有票源。

  销售柜台:3号窗口没有获得票源!

  销售柜台:2号窗口卖了一张票,剩下一张是1。

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余票为0

  销售柜台:3号窗口没有获得票源!

  销售柜台:2号窗口没有获得票源!

  流程结束退出代码0//如果没有拿到货源的开票,就不用等了。转到下一次购票tryLock(长时间,时间单位单位)

  TryLock(long time,TimeUnit单位)可以设置为在无法获得锁的情况下等待一段时间。//第一个参数总是长整型,第二个参数是时间单位

  公共类SellRunnable实现Runnable {

  //有十张票。

  int index=10

  lock lock=new reentrant lock();

  public void sell() {

  尝试{

  if (lock.tryLock(1000,时间单位。毫秒)){

  尝试{

  System.out.println(销售计数器: Thread.currentThread()。getName()

  获取票源’);

  if (index=1) {

  索引-;

  System.out.println(销售计数器: Thread.currentThread()。getName()

  卖了一张票,剩下的:‘指数);

  }否则{

  System.out.println(销售计数器: Thread.currentThread())。

  GetName()买的时候没有000的票));

  }

  尝试{

  线程.睡眠(2000年);//人为加入购票时间

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  }最后{

  lock . unlock();

  }

  }否则{

  System.out.println(销售计数器: Thread.currentThread()。getName()

  没有获得票源! );

  }

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  }

  @覆盖

  公共无效运行(){

  while(索引0) {

  尝试{

  thread . sleep(500);//否则执行太快看不到效果。

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  sell();

  }

  }

  }执行结果:

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余9张

  销售柜台:2号窗口没有获得票源!

  销售柜台:3号窗口没有获得票源!

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口卖了一张票,剩余8张。

  销售柜台:3号窗口没有获得票源!

  销售柜台:1号窗口没有获得票源!

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口售出一张票,剩余数量为7张。

  销售柜台:1号窗口没有获得票源!

  销售柜台:2号窗口没有获得票源!

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余6张

  销售柜台:2号窗口没有获得票源!

  销售柜台:3号窗口没有获得票源!

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口售出一张票,剩余5张

  销售柜台:3号窗口没有获得票源!

  销售柜台:1号窗口没有获得票源!

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口售出一张票,剩余数量为4张。

  销售柜台:1号窗口没有获得票源!

  销售柜台:2号窗口没有获得票源!

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余的3张

  销售柜台:2号窗口没有获得票源!

  销售柜台:3号窗口没有获得票源!

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口售出一张票,剩余的票是2

  销售柜台:3号窗口没有获得票源!

  销售柜台:1号窗口没有获得票源!

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口卖了一张票,剩下一张是1。

  销售柜台:1号窗口没有获得票源!

  销售柜台:2号窗口没有获得票源!

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余票为0

  销售柜台:2号窗口没有获得票源!

  销售柜台:3号窗口没有获得票源!

  流程结束退出代码0 //当购票时间约为等待时间时,无票源的窗口不购票,进入下一个购票机会会缩短购票时间:

  尝试{

  thread . sleep(500);//人为加入购票时间

  } catch (InterruptedException e) {

  e . printstacktrace();

  }执行结果:

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余9张

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口卖了一张票,剩余8张。

  销售柜台:3号窗口没有获得票源!

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余7张

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口售出一张票,剩余6张

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余5张

  销售柜台:3号窗口没有获得票源!

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口售出一张票,剩余数量为4张。

  销售柜台:3号窗口有票源。

  销售柜台:一张票在3号窗口售出,剩下的是3张

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余的2

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口卖了一张票,剩下一张是1。

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口售出一张票,剩余:0

  销售柜台:1号窗口有票源。

  销售柜台:1000号窗口没有票。

  销售柜台:2号窗口有票源。

  销售柜台:2000号窗口没有票。

  过程结束,退出代码为0 //如果在等待时间内获得票源,将售出车票。

  当lockinterrupt()通过这个方法获取一个锁时,如果这个锁正在被其他线程持有,那么它将进入等待状态,但是这个等待过程是可以被中断的。可以通过调用Thread对象的interrupt方法来中断等待,中断时抛出InterruptedException,需要捕捉或声明抛出。

  公共类ThreadTest {

  公共静态void main(String[] args) {

  sell runnable sell runnable=new sell runnable();

  ThreadThread1=新线程(sellrunnable, window 1 );

  ThreadThread2=新线程(sellrunnable, window 2 );

  ThreadThread3=新线程(sellrunnable, window 3 );

  thread 1 . start();

  尝试{

  thread . sleep(500);//确保1号窗口首先获得锁

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  thread 2 . start();

  thread 3 . start();

  尝试{

  线程.睡眠(2000年);//等待两秒后,中断windows 2和3的等待。

  } catch (InterruptedException e) {

  e . printstacktrace();

  }

  thread2.interrupt()。

  thread3.interrupt()。

  }

  }

  SellRunnable中的长等待时间:

  尝试{

  thread . sleep(5000);//人为加入购票时间

  } catch (InterruptedException e) {

  e . printstacktrace();

  }执行结果:

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余9张

  销售柜台:3号窗口中断//这个地方中断。

  销售柜台:2号窗口中断//这个地方中断。

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口卖了一张票,剩余8张。

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口售出一张票,剩余数量为7张。

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余6张

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口售出一张票,剩余5张

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口售出一张票,剩余数量为4张。

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余的3张

  销售柜台:2号窗口有票源。

  销售柜台:2号窗口售出一张票,剩余的票是2

  销售柜台:3号窗口有票源。

  销售柜台:3号窗口卖了一张票,剩下一张是1。

  销售柜台:1号窗口有票源。

  销售柜台:1号窗口售出一张票,剩余票为0

  销售柜台:2号窗口有票源。

  销售柜台:2000号窗口没有票。

  销售柜台:3号窗口有票源。

  销售柜台:3000号窗口没有票。

  过程结束,退出代码为0synchronized和Lock对比

  通过上面的代码,我们可以看到Lock和synchronized之间的几个联系和区别:

  两个都是重入锁。

  重入锁是指在一个线程获得一个对象的锁后,该线程可以再次获得该对象的锁而不被阻塞。比如同一个类中的多个方法(或者一个方法的递归调用)被synchronized修饰或者被Lock加持后,同一个线程在调用这两个方法时可以获得对象的锁而不会被阻塞。

  不可重入锁的例子:

  公共类锁{

  私有布尔值isLocked=false

  公共void锁(){

  while(isLocked){

  wait();

  }

  isLocked=true

  }

  公共void解锁(){

  isLocked=false

  notify();

  }

  }

  //用法:

  公共类测试{

  Lock Lock=new Lock();

  公共void test1(){

  lock . lock();

  test2();

  lock . unlock();

  }

  public void test2(){

  lock . lock();

  .

  lock . unlock();

  }

  }当}Test类调用test1方法,执行lock.lock()后调用test2时,会一直等待,变成死锁。

  重入锁的设计原则:

  公共类锁{

  私有布尔值isLocked=false

  私有线程lockedThread=null

  int locked count=0;

  公共void锁(){

  thread thread=thread . current thread();

  while(isLocked线程!=lockedThread){

  wait();

  }

  isLocked=true

  lockedCount

  lockedThread=thread

  }

  公共void解锁(){

  thread thread=thread . current thread();

  if(thread==lockedThread){

  locked count-;

  if(lockedCount==0){

  isLocked=false

  lockedThread=null

  notify();

  }

  }

  }

  }这样调用Test类的Test1方法后,test2方法也可以成功执行。

  Synchronized基本上是通过计数器的方式实现可重入的。

  Lock是可中断锁,synchronized是不能中断的。

  当A线程B执行被锁对象的代码,发现A线程已经持有锁,那么B线程会等待,但是synchronized不能中断等待过程,lock可以通过lockInterruptibly方法抛出异常来中断等待,处理其他事情。

  Lock可以创建公平锁,synchronized是不公平锁。

  公平锁意味着锁是按照请求的顺序获取的,但是不公平锁不能保证线程获取锁的顺序。

  Lock可以知道锁是否被获取,synchronized则不能。

  当异常发生或操作完成时,Synchronized将自动释放线程持有的锁。锁需要主动解锁,否则会被锁住;

  当synchronized被阻塞时,其他线程不能获得锁,但lock可以(这也是锁设计的目的之一)。

  读写锁

  当多个线程写入同一个文件时,会产生冲突,所以需要锁定它。但是,当读取同一个文件时,使用上述方法会降低效率。因此,基于这种情况,创建了读写锁接口:

  公共接口读写锁{

  /**

  *返回用于读取的锁。

  *

  * @返回用于读取的锁。

  */

  lock read lock();//读取锁

  /**

  *返回用于写入的锁。

  *

  * @返回用于写入的锁。

  */

  lock writeLock();//写锁

  }这个接口的实现类是ReentrantReadWriteLock,其源代码如下:

  公共类ReentrantReadWriteLock实现读写锁,Serializable {

  private static final long serialVersionUID=-6992448646407690164 l;

  私有final ReentrantReadWriteLock。ReadLock readerLock

  私有final ReentrantReadWriteLock。WriteLock writerLock

  .

  publicreentrantreadwritelock . write lock writelock(){//Get writelock

  返回this.writerLock

  }

  publicreentrantreadwritelock . read lock read lock(){//Get read lock

  返回this.readerLock

  }

  .

  }使用与Lock相同的方法。使用write时,调用writeLock()方法获得锁,使用read时,调用readLock()方法获得锁。需要注意的知识点如下:

  线程A占用写锁,线程B在申请读写时需要等待。

  线程A占用读锁,线程B在申请写操作时需要等待。

  线程A占用读锁,线程B在获取读操作时可以获取读锁。

  总结

  如果需要提高效率,建议使用Lock。如果效率不高,那么synchronized满足使用条件,业务逻辑编写简单,不需要手动解锁。

  PHP中文网站,有很多免费的JAVA入门教程,欢迎学习!即java线程同步的细节是什么,更多请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: