「java策略锁」java的锁机制

博主:adminadmin 2022-12-21 01:36:10 86

今天给各位分享java策略锁的知识,其中也会对java的锁机制进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

java 哪个锁是非重入的

读写锁 ReadWriteLock读写锁维护了一对相关的锁,一个用于只读操作,一个用于写入操作。只要没有writer,读取锁可以由多个reader线程同时保持。写入锁是独占的。

互斥锁一次只允许一个线程访问共享数据,哪怕进行的是只读操作;读写锁允许对共享数据进行更高级别的并发访问:对于写操作,一次只有一个线程(write线程)可以修改共享数据,对于读操作,允许任意数量的线程同时进行读取。

与互斥锁相比,使用读写锁能否提升性能则取决于读写操作期间读取数据相对于修改数据的频率,以及数据的争用——即在同一时间试图对该数据执行读取或写入操作的线程数。

读写锁适用于读多写少的情况。

可重入读写锁 ReentrantReadWriteLock

属性ReentrantReadWriteLock 也是基于 AbstractQueuedSynchronizer 实现的,它具有下面这些属性(来自Java doc文档):

* 获取顺序:此类不会将读取者优先或写入者优先强加给锁访问的排序。

* 非公平模式(默认):连续竞争的非公平锁可能无限期地推迟一个或多个reader或writer线程,但吞吐量通常要高于公平锁。

* 公平模式:线程利用一个近似到达顺序的策略来争夺进入。当释放当前保持的锁时,可以为等待时间最长的单个writer线程分配写入锁,如果有一组等待时间大于所有正在等待的writer线程的reader,将为该组分配读者锁。

* 试图获得公平写入锁的非重入的线程将会阻塞,除非读取锁和写入锁都自由(这意味着没有等待线程)。

* 重入:此锁允许reader和writer按照 ReentrantLock 的样式重新获取读取锁或写入锁。在写入线程保持的所有写入锁都已经释放后,才允许重入reader使用读取锁。

writer可以获取读取锁,但reader不能获取写入锁。

* 锁降级:重入还允许从写入锁降级为读取锁,实现方式是:先获取写入锁,然后获取读取锁,最后释放写入锁。但是,从读取锁升级到写入锁是不可能的。

* 锁获取的中断:读取锁和写入锁都支持锁获取期间的中断。

* Condition 支持:写入锁提供了一个 Condition 实现,对于写入锁来说,该实现的行为与 ReentrantLock.newCondition() 提供的Condition 实现对 ReentrantLock 所做的行为相同。当然,此 Condition 只能用于写入锁。

读取锁不支持 Condition,readLock().newCondition() 会抛出 UnsupportedOperationException。

* 监测:此类支持一些确定是读取锁还是写入锁的方法。这些方法设计用于监视系统状态,而不是同步控制。

实现AQS 回顾在之前的文章已经提到,AQS以单个 int 类型的原子变量来表示其状态,定义了4个抽象方法( tryAcquire(int)、tryRelease(int)、tryAcquireShared(int)、tryReleaseShared(int),前两个方法用于独占/排他模式,后两个用于共享模式 )留给子类实现,用于自定义同步器的行为以实现特定的功能。

对于 ReentrantLock,它是可重入的独占锁,内部的 Sync 类实现了 tryAcquire(int)、tryRelease(int) 方法,并用状态的值来表示重入次数,加锁或重入锁时状态加 1,释放锁时状态减 1,状态值等于 0 表示锁空闲。

对于 CountDownLatch,它是一个关卡,在条件满足前阻塞所有等待线程,条件满足后允许所有线程通过。内部类 Sync 把状态初始化为大于 0 的某个值,当状态大于 0 时所有wait线程阻塞,每调用一次 countDown 方法就把状态值减 1,减为 0 时允许所有线程通过。利用了AQS的共享模式。

现在,要用AQS来实现 ReentrantReadWriteLock。

一点思考问题

* AQS只有一个状态,那么如何表示 多个读锁 与 单个写锁 呢?

* ReentrantLock 里,状态值表示重入计数,现在如何在AQS里表示每个读锁、写锁的重入次数呢?

* 如何实现读锁、写锁的公平性呢?

在java中,死锁形成的原因是?

死锁是进程死锁的简称,是由Dijkstra于1965年研究银行家算法时首先提出来的。它是计算机操作系统乃至并发程序设计中最难处理的问题之一。实际上,死锁问题不仅在计算机系统中存在,在我们日常生活中它也广泛存在。

1.什么是死锁

我们先看看这样一个生活中的例子:在一条河上有一座桥,桥面较窄,只能容纳一辆汽车通过,无法让两辆汽车并行。如果有两辆汽车A和B分别由桥的两端驶上该桥,则对于A车来说,它走过桥面左面的一段路(即占有了桥的一部分资源),要想过桥还须等待B车让出右边的桥面,此时A车不能前进;对于B车来说,它走过桥面右边的一段路(即占有了桥的一部分资源),要想过桥还须等待A车让出左边的桥面,此时B车也不能前进。两边的车都不倒车,结果造成互相等待对方让出桥面,但是谁也不让路,就会无休止地等下去。这种现象就是死锁。如果把汽车比做进程,桥面作为资源,那麽上述问题就描述为:进程A占有资源R1,等待进程B占有的资源Rr;进程B占有资源Rr,等待进程A占有的资源R1。而且资源R1和Rr只允许一个进程占用,即:不允许两个进程同时占用。结果,两个进程都不能继续执行,若不采取其它措施,这种循环等待状况会无限期持续下去,就发生了进程死锁。

在计算机系统中,涉及软件,硬件资源都可能发生死锁。例如:系统中只有一台CD-ROM驱动器和一台打印机,某一个进程占有了CD-ROM驱动器,又申请打印机;另一进程占有了打印机,还申请CD-ROM。结果,两个进程都被阻塞,永远也不能自行解除。

所谓死锁,是指多个进程循环等待它方占有的资源而无限期地僵持下去的局面。很显然,如果没有外力的作用,那麽死锁涉及到的各个进程都将永远处于封锁状态。从上面的例子可以看出,计算机系统产生死锁的根本原因就是资源有限且操作不当。即:一种原因是系统提供的资源太少了,远不能满足并发进程对资源的需求。这种竞争资源引起的死锁是我们要讨论的核心。例如:消息是一种临时性资源。某一时刻,进程A等待进程B发来的消息,进程B等待进程C发来的消息,而进程C又等待进程A发来的消息。消息未到,A,B,C三个进程均无法向前推进,也会发生进程通信上的死锁。另一种原因是由于进程推进顺序不合适引发的死锁。资源少也未必一定产生死锁。就如同两个人过独木桥,如果两个人都要先过,在独木桥上僵持不肯后退,必然会应竞争资源产生死锁;但是,如果两个人上桥前先看一看有无对方的人在桥上,当无对方的人在桥上时自己才上桥,那麽问题就解决了。所以,如果程序设计得不合理,造成进程推进的顺序不当,也会出现死锁。

2.产生死锁的必要条件

从以上分析可见,如果在计算机系统中同时具备下面四个必要条件时,那麽会发生死锁。换句话说,只要下面四个条件有一个不具备,系统就不会出现死锁。

〈1〉互斥条件。即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有。这种独占资源如CD-ROM驱动器,打印机等等,必须在占有该资源的进程主动释放它之后,其它进程才能占有该资源。这是由资源本身的属性所决定的。如独木桥就是一种独占资源,两方的人不能同时过桥。

〈2〉不可抢占条件。进程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放。如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人自己过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。

〈3〉占有且申请条件。进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时,仍继续占用已占有的资源。还以过独木桥为例,甲乙两人在桥上相遇。甲走过一段桥面(即占有了一些资源),还需要走其余的桥面(申请新的资源),但那部分桥面被乙占有(乙走过一段桥面)。甲过不去,前进不能,又不后退;乙也处于同样的状况。

〈4〉循环等待条件。存在一个进程等待序列{P1,P2,...,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,......,而Pn等待P1所占有的的某一资源,形成一个进程循环等待环。就像前面的过独木桥问题,甲等待乙占有的桥面,而乙又等待甲占有的桥面,从而彼此循环等待。

上面我们提到的这四个条件在死锁时会同时发生。也就是说,只要有一个必要条件不满足,则死锁就可以排除。

8.2 死锁的预防

前面介绍了死锁发生时的四个必要条件,只要破坏这四个必要条件中的任意一个条件,死锁就不会发生。这就为我们解决死锁问题提供了可能。一般地,解决死锁的方法分为死锁的预防,避免,检测与恢复三种(注意:死锁的检测与恢复是一个方法)。我们将在下面分别加以介绍。

死锁的预防是保证系统不进入死锁状态的一种策略。它的基本思想是要求进程申请资源时遵循某种协议,从而打破产生死锁的四个必要条件中的一个或几个,保证系统不会进入死锁状态。

Java中Lock,tryLock,lockInterruptibly有什么区别

ReentrantLock锁有好几种,除了常用的lock,tryLock,其中有个lockInterruptibly。先把API粘贴上来lockpublicvoidlock()获取锁。如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为1。如果当前线程已经保持该锁,则将保持计数加1,并且该方法立即返回。如果该锁被另一个线程保持,则出于线程调度的目的,禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态,此时锁保持计数被设置为1。指定者:接口Lock中的locklockInterruptiblypublicvoidlockInterruptibly()throwsInterruptedException1)如果当前线程未被中断,则获取锁。2)如果该锁没有被另一个线程保持,则获取该锁并立即返回,将锁的保持计数设置为1。3)如果当前线程已经保持此锁,则将保持计数加1,并且该方法立即返回。4)如果锁被另一个线程保持,则出于线程调度目的,禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态:1)锁由当前线程获得;或者2)其他某个线程中断当前线程。5)如果当前线程获得该锁,则将锁保持计数设置为1。如果当前线程:1)在进入此方法时已经设置了该线程的中断状态;或者2)在等待获取锁的同时被中断。则抛出InterruptedException,并且清除当前线程的已中断状态。6)在此实现中,因为此方法是一个显式中断点,所以要优先考虑响应中断,而不是响应锁的普通获取或重入获取。指定者:接口Lock中的lockInterruptibly抛出:InterruptedException如果当前线程已中断。tryLockpublicbooleantryLock()仅在调用时锁未被另一个线程保持的情况下,才获取该锁。1)如果该锁没有被另一个线程保持,并且立即返回true值,则将锁的保持计数设置为1。即使已将此锁设置为使用公平排序策略,但是调用tryLock()仍将立即获取锁(如果有可用的),而不管其他线程当前是否正在等待该锁。在某些情况下,此“闯入”行为可能很有用,即使它会打破公平性也如此。如果希望遵守此锁的公平设置,则使用tryLock(0,TimeUnit.SECONDS),它几乎是等效的(也检测中断)。2)如果当前线程已经保持此锁,则将保持计数加1,该方法将返回true。3)如果锁被另一个线程保持,则此方法将立即返回false值。指定者:接口Lock中的tryLock返回:如果锁是自由的并且被当前线程获取,或者当前线程已经保持该锁,则返回true;否则返回false关于中断又是一段很长的叙述,先不谈。1)lock(),拿不到lock就不罢休,不然线程就一直block。比较无赖的做法。2)tryLock(),马上返回,拿到lock就返回true,不然返回false。比较潇洒的做法。带时间限制的tryLock(),拿不到lock,就等一段时间,超时返回false。比较聪明的做法。3)lockInterruptibly()就稍微难理解一些。先说说线程的打扰机制,每个线程都有一个打扰标志。这里分两种情况,1.线程在sleep或wait,join,此时如果别的进程调用此进程的interrupt()方法,此线程会被唤醒并被要求处理InterruptedException;(thread在做IO操作时也可能有类似行为,见javathreadapi)2.此线程在运行中,则不会收到提醒。但是此线程的“打扰标志”会被设置,可以通过isInterrupted()查看并作出处理。lockInterruptibly()和上面的第一种情况是一样的,线程在请求lock并被阻塞时,如果被interrupt,则“此线程会被唤醒并被要求处理InterruptedException”。并且如果线程已经被interrupt,再使用lockInterruptibly的时候,此线程也会被要求处理interruptedException先看lock()方法importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;/***@author作者E-mail:*@version创建时间:2015-10-23下午01:47:03类说明*/publicclassTestLock{//@Testpublicvoidtest()throwsException{finalLocklock=newReentrantLock();lock.lock();Threadt1=newThread(newRunnable(){@Overridepublicvoidrun(){lock.lock();System.out.println(Thread.currentThread().getName()+"interrupted.");}},"childthread-1");t1.start();Thread.sleep(1000);t1.interrupt();Thread.sleep(1000000);}publicstaticvoidmain(String[]args)throwsException{newTestLock().test();}}用eclipse对这个程序进行debug发现,即使子线程已经被打断,但是子线程仍然在run,可见lock()方法并不关心线程是否被打断,甚至说主线程已经运行完毕,子线程仍然在block().而使用LockInterupptibly,则会响应中断importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;/***@author作者E-mail:*@version创建时间:2015-10-23下午01:53:10类说明*/publicclassTestLockInterruptibly{//@Testpublicvoidtest3()throwsException{finalLocklock=newReentrantLock();lock.lock();Threadt1=newThread(newRunnable(){@Overridepublicvoidrun(){try{lock.lockInterruptibly();}catch(InterruptedExceptione){System.out.println(Thread.currentThread().getName()+"interrupted.");}}},"childthread-1");t1.start();Thread.sleep(1000);t1.interrupt();Thread.sleep(1000000);}publicstaticvoidmain(String[]args)throwsException{newTestLockInterruptibly().test3();}}try{Thread.sleep(2000);lock.lockInterruptibly();}catch(InterruptedExceptione){System.out.println(Thread.currentThread().getName()+"interrupted.");}t1.start();t1.interrupt();Thread.sleep(1000000);如果将代码改成这样,那么将会在在阻塞之前已经中断,此时再lockInterruptibly()也是会相应中断异常的

java多线程,对象锁是什么概念?

java线程:

1.线程中一些基本术语和概念

1.1线程的几个状态

初始化状态

就绪状态

运行状态

阻塞状态

终止状态

1.2 Daemon线程

Daemon线程区别一般线程之处是:主程序一旦结束,Daemon线程就会结束。

1.3锁的定义

为了协调多个并发运行的线程使用共享资源才引入了锁的概念。

1.4死锁

任何多线程应用程序都有死锁风险。当一组线程中的每一个都在等待一个只

有该组中另一个线程才能引起的事件时,我们就说这组线程死锁了。换一个说法

就是一组线程中的每一个成员都在等待别的成员占有的资源时候,就可以说这组

线程进入了死锁。死锁的最简单情形是:线程 A 持有对象 X 的独占锁,并且

在等待对象 Y 的锁,而线程 B 持有对象 Y 的独占锁,却在等待对象 X 的锁。

除非有某种方法来打破对锁的等待(Java 锁定不支持这种方法),否则死锁的线

程将永远等下去。

1.5.Java对象关于锁的几个方法

1.5.1 wait方法

wait方法是java根对象Object含有的方法,表示等待获取某个锁。在wait方法进入前,会释放相应的锁,在wait方法返回时,会再次获得某个锁。

如果wait()方法不带有参数,那只有当持有该对象锁的其他线程调用了notify或者notifyAll方法,才有可能再次获得该对象的锁。

如果wait()方法带有参数,比如:wait(10),那当持有该对象锁的其他线程调用了notify或者notifyAll方法,或者指定时间已经过去了,才有可能再次获得该对象的锁。

参考 thread.lock.SleepAndWait

1.5.2 notify/notifyAll方法

这里我就不再说明了。哈哈,偷点懒。

1.5.3 yield方法

yield()会自动放弃CPU,有时比sleep更能提升性能。

1.6锁对象(实例方法的锁)

在同步代码块中使用锁的时候,担当锁的对象可以是这个代码所在对象本身或者一个单独的对象担任,但是一定要确保锁对象不能为空。如果对一个null对象加锁,会产生异常的。原则上不要选择一个可能在锁的作用域中会改变值的实例变量作为锁对象。

锁对象,一种是对象自己担任,一种是定义一个普通的对象作为private property来担任,另外一种是建立一个新的类,然后用该类的实例来担任。

参考 :

thread.lock.UseSelfAsLock,使用对象自己做锁对象

thread.lock.UseObjAsLock 使用一个实例对象作锁对象

thread.lock.UseAFinalObjAsLock使用常量对象作为一个锁对象

1.7类锁

实例方法存在同步的问题,同样,类方法也存在需要同步的情形。一般类方法的类锁是一个static object来担任的。当然也可以采用类本身的类对象来作为类锁。

一个类的实例方法可以获得该类实例锁,还可以尝试去访问类方法,包含类同步方法,去获得类锁。

一个类的类方法,可以尝试获得类锁,但是不可以尝试直接获得实例锁。需要先生成一个实例,然后在申请获得这个实例的实例锁。

参考

thread.lock.UseStaticObjAsStaticLock 使用类的属性对象作为类锁。

thread.lock.UseClassAsStaticLock使用类的类对象作为类锁

1.8.线程安全方法与线程不安全方法

如果一个对象的所有的public方法都是同步方法,也就是说是public方法是线程安全的,那该对象的private方法,在不考虑继承的情况下,可以设置为不是线程安全的方法。

参考 thread.lock.SynMethrodAndNotSynMethrod

1.9类锁和实例锁混合使用

在实例方法中混合使用类锁和实例锁;可以根据前面说的那样使用实例锁和类锁。

在类方法中混合使用类锁和实例锁,可以根据前面说的那样使用类锁,为了使用实例锁,先得生成一个实例,然后实例锁。

参考 thread.lock.StaticLockAndObjLock

1.10锁的粒度问题。

为了解决对象锁的粒度过粗,会导死锁出现的可能性加大,锁的粒度过细,会程序开发维护的工作加大。对于锁的粒度大小,这完全要根据实际开发需要来考虑,很难有一个统一的标准。

1.11.读写锁

一个读写锁支持多个线程同时访问一个对象,但是在同一时刻只有一个线程可以修改此对象,并且在访问进行时不能修改。

有2种调度策略,一种是读锁优先,另外就是写锁优先。

参考 thread.lock.ReadWriteLock

1.12 volatile

在Java中设置变量值的操作,除了long和double类型的变量外都是原子操作,也就是说,对于变量值的简单读写操作没有必要进行同步。这在JVM 1.2之前,Java的内存模型实现总是从主存读取变量,是不需要进行特别的注意的。而随着JVM的成熟和优化,现在在多线程环境下volatile关键字的使用变得非常重要。在当前的Java内存模型下,线程可以把变量保存在本地内存(比如机器的寄存器)中,而不是直接在主存中进行读写。这就可能造成一个线程在主存中修改了一个变量的值,而另外一个线程还继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。要解决这个问题,只需要像在本程序中的这样,把该变量声明为volatile(不稳定的)即可,这就指示JVM,这个变量是不稳定的,每次使用它都到主存中进行读取。一般说来,多任务环境下各任务间共享的标志都应该加volatile修饰。

2.线程之间的通讯

在其他语言中,线程之间可以通过消息队列,共享内存,管道等方式来实现

线程之间的通讯,但是java中可以不采用这样方式,关注的是线程之间的同步。

只要保证相关方法运行的线程安全,信息共享是自然就可以显现了。

2.1屏障

屏障就是这样的一个等待点: 一组线程在这一点被同步,这些线程合并各自的结果或者运行到整体任务的下一阶段。

参考:

thread.lock. BarrierUseExample

thread.lock.Barrier

2.2.锁工具类

提供对线程锁的获取,释放功能。展示了锁的获取释放过程。可以作为一个工具类来使用。

参考:thread.lock. BusyFlag

2.3.条件变量

条件变量是POSIX线程模型提供的一种同步类型,和java中的等待通知机制类似。

虽然java中已经有了等待通知机制,但是为了减少在notify/notifyAll方法中

线程调度的开销,把一些不需要激活的线程屏蔽出去,引入了条件变量。

Java中2个(多个)条件变量可以是同一个互斥体(锁对象)。

参考:thread.lock.CondVar 条件变量类

常见的应用情形:

一个锁控制多个信号通道(例如:多个变量),虽然可以采用简单java等待通知机制,但是线程调度效率不高,而且线程可读性也不是太好,这时候可以采用创建一个锁对象(BusyFlag实例),同时使用这个BusyFlag实例来创建多个条件变量(CondVar 实例)。

经常使用到CondVar类的地方是缓冲区管理,比如:管道操作之类的。先创建一个BusyFlag实例,然后创建CondVar 实例,用这个条件变量描述缓冲区是否为空,另外创建CondVar 实例作条件变量述缓冲区是否满。

现实中,马路的红绿灯,就可以采用条件变量来描述。

3. Java线程调度

3.1 Java优先级

java的优先级别共有10种,加上虚拟机自己使用的优先级别=0这种,总共11种。

大多数情况来说,java线程的优先级设置越高(最高=10),那线程越优先运行。

3.2. 绿色线程

线程运行在虚拟机内,操作系统根本不知道这类线程的存在。

线程是由虚拟机调度的。

3.3 本地线程

线程是由运行虚拟机的操作系统完成的。

3.4 Windows本地线程

操作系统,完全能够看得到虚拟机内的每一个线程,同时虚拟机的线程和操作系统的线程是一一对应的。Java的线程调度室由操作系统底层线程决定的。

在win32平台下,windows线程只有6个优先级别。和java线程优先级别对应如下:

Java线程优先级 Windows 95/nt/2000线程优先级

0 THREAD_ PRIORITY_IDLE

1(Thread.MIN_PRIORITY) THREAD_ PRIORITY_LOWEST

2 THREAD_ PRIORITY_LOWEST

3 THREAD_ PRIORITY_BELOW_NORMAL

4 THREAD_ PRIORITY_BELOW_NORMAL

5 (Thread.NORM_PRIORITY) THREAD_ PRIORITY _NORMAL

6 THREAD_ PRIORITY _ABOVE_NORMAL

7 THREAD_ PRIORITY _ABOVE_NORMA

8 THREAD_ PRIORITY _HIGHEST

9 THREAD_ PRIORITY _HIGHEST

10 (Thread.MAX_PRIORITY) THREAD_ PRIORITY _CRITICAL

3.5线程优先级倒置与继承

如果一个线程持有锁(假设该线程名字=ThreadA,优先级别=5),另外一个线程(假设该线程名字=ThreadB,优先级别=7),现在该线程(ThreadA)处于运行状态,但是线程ThreadB申请需要持有ThreadA所获得的锁,这时候,为了避免死锁,线程A提高其运行的优先级别(提高到ThreadB的优先级别=7),而线程ThreadB为了等待获得锁,降低线程优先级别(降低到ThreadA原来的优先级别=5).

上述的这种情况,对于ThreadA,继承了ThreadB的优先级别,这成为优先级别的继承;对于ThreadB暂时降低了优先级别,成为优先级别的倒置。

当然,一旦线程ThreadA持有的锁释放了,其优先级别也会回到原来的优先级别(优先级别=5)。线程ThreadB获得了相应的锁,那优先级别也会恢复到与原来的值(优先级别=7)。

3.6循环调度

具有同样优先级的线程相互抢占成为循环调度。

4.线程池

创建一个线程也是需要一定代价的,为了降低这个代价,采用了和普通对象池的思想建立线程池,以供系统使用。

线程消耗包括内存和其它系统资源在内的大量资源。除了 Thread 对象所需的内存之外,每个线程都需要两个可能很大的执行调用堆栈。除此以外,JVM 可能会为每个 Java 线程创建一个本机线程,这些本机线程将消耗额外的系统资源。最后,虽然线程之间切换的调度开销很小,但如果有很多线程,环境切换也可能严重地影响程序的性能。

使用线程池的方式是,先建立对象池,然后申请使用线程,程序线程运行,运行完毕,把线程返回线程池。

使用线程池的风险:同步错误和死锁,与池有关的死锁、资源不足和线程泄漏。

大家有空可以研究一下tomcat的线程池实现原理思想。

实际上是tomcat已经在从线程池的使用线程时候加上了事件处理机制。

个人认为,线程池之类的实现,一般不要自己实现,因为自己实现主要是稳定性等方面可能作的不够好。

可以参考 apache的jakarta-tomcat-5.5.6的相关代码,具体是:

jakarta-tomcat-connectors\util\java\org\apache\tomcat\util\threads的相关代码

5工作队列

使用工作队列的好处是不象直接使用线程池那样,当线城池中没有线程可以使用的时

候,使用者需要处于等待状态,不能进行其他任务的处理。

工作队列的工作原理是:

采用后台线程处理方式,客户端把任务提交给工作队列,工作队列有一组内部可以工作线程,这些工作线程从工作队列中取出任务运行,一个任务完成后,就从队列获取下一个任务进行处理。当工作队列中没有任务可以处理时候,工作线程就处于等待状态,直到获得新的任务时候,才进行新的处理。

java同步锁慢怎么解决

百度知道

java同步锁慢怎么解决

173******87

超过41用户采纳过TA的回答

关注

成为第1位粉丝

性能优化的需求实现中,如果使用了多线程并行来提高程序运行效率,那么一个很难绕开的部分就是同步加锁。同步锁会将多线程并行执行强制合流为串行执行,通常会成为整个程序的性能瓶颈所在,所以锁性能的优化必不可少。一般来说,优化锁性能的关键如下:

降低锁竞争概率

提高锁竞争效率

1. 降低锁竞争概率

1.1 减小锁粒度

要降低锁竞争发生的概率,一个非常直观的思路是减小锁粒度,核心思想是将大的全局锁分割为一个个范围精确的小锁,使线程的竞争对象从全局锁变更为小锁,从而减少锁竞争发生

java两个线程锁的问题:当两个线程都被锁了,而且各自调用的方法里有同一个对象,那么只能运行一个线程

我明白了你的意思了,当两个线程都被锁定了以后,如果含有相同对象则只有当一个线程运行结束以后释放资源,另一个线程才能执行,获得此资源;但是如果不含有相同的资源,则互不影响,自己运行自己的,当CPU分给他时间片他就可以运行。

java策略锁的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于java的锁机制、java策略锁的信息别忘了在本站进行查找喔。

The End

发布于:2022-12-21,除非注明,否则均为首码项目网原创文章,转载请注明出处。