java同步锁用什么释放 java线程同步问题
大家好,关于java同步锁用什么释放很多朋友都还不太明白,今天小编就来为大家分享关于java线程同步问题的知识,希望对各位有所帮助!
synchronized 加在java方法前面是什么作用
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
举例说明:
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
package ths;
public class Thread1 implements Runnable{
public void run(){
synchronized(this){
for(int i= 0; i< 5; i++){
System.out.println(Thread.currentThread().getName()+" synchronized loop"+ i);
}
}
}
public static void main(String[] args){
Thread1 t1= new Thread1();
Thread ta= new Thread(t1,"A");
Thread tb= new Thread(t1,"B");
ta.start();
tb.start();
}
}
结果:
A synchronized loop 0
A synchronized loop 1
A synchronized loop 2
A synchronized loop 3
A synchronized loop 4
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
package ths;
public class Thread2{
public void m4t1(){
synchronized(this){
int i= 5;
while( i--> 0){
System.out.println(Thread.currentThread().getName()+":"+ i);
try{
Thread.sleep(500);
} catch(InterruptedException ie){
}
}
}
}
public void m4t2(){
int i= 5;
while( i--> 0){
System.out.println(Thread.currentThread().getName()+":"+ i);
try{
Thread.sleep(500);
} catch(InterruptedException ie){
}
}
}
public static void main(String[] args){
final Thread2 myt2= new Thread2();
Thread t1= new Thread( new Runnable(){ public void run(){ myt2.m4t1();}},"t1");
Thread t2= new Thread( new Runnable(){ public void run(){ myt2.m4t2();}},"t2");
t1.start();
t2.start();
}
}
结果:
t1: 4
t2: 4
t1: 3
t2: 3
t1: 2
t2: 2
t1: 1
t2: 1
t1: 0
t2: 0
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
//修改Thread2.m4t2()方法:
public void m4t2(){
synchronized(this){
int i= 5;
while( i--> 0){
System.out.println(Thread.currentThread().getName()+":"+ i);
try{
Thread.sleep(500);
} catch(InterruptedException ie){
}
}
}
}
结果:
t1: 4
t1: 3
t1: 2
t1: 1
t1: 0
t2: 4
t2: 3
t2: 2
t2: 1
t2: 0
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
//修改Thread2.m4t2()方法如下:
public synchronized void m4t2(){
int i= 5;
while( i--> 0){
System.out.println(Thread.currentThread().getName()+":"+ i);
try{
Thread.sleep(500);
} catch(InterruptedException ie){
}
}
}
结果:
t1: 4
t1: 3
t1: 2
t1: 1
t1: 0
t2: 4
t2: 3
t2: 2
t2: 1
t2: 0
五、以上规则对其它对象锁同样适用:
package ths;
public class Thread3{
class Inner{
private void m4t1(){
int i= 5;
while(i--> 0){
System.out.println(Thread.currentThread().getName()+": Inner.m4t1()="+ i);
try{
Thread.sleep(500);
} catch(InterruptedException ie){
}
}
}
private void m4t2(){
int i= 5;
while(i--> 0){
System.out.println(Thread.currentThread().getName()+": Inner.m4t2()="+ i);
try{
Thread.sleep(500);
} catch(InterruptedException ie){
}
}
}
}
private void m4t1(Inner inner){
synchronized(inner){//使用对象锁
inner.m4t1();
}
private void m4t2(Inner inner){
inner.m4t2();
}
public static void main(String[] args){
final Thread3 myt3= new Thread3();
final Inner inner= myt3.new Inner();
Thread t1= new Thread( new Runnable(){public void run(){ myt3.m4t1(inner);}},"t1");
Thread t2= new Thread( new Runnable(){public void run(){ myt3.m4t2(inner);}},"t2");
t1.start();
t2.start();
}
}
结果:
尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。
t1: Inner.m4t1()=4
t2: Inner.m4t2()=4
t1: Inner.m4t1()=3
t2: Inner.m4t2()=3
t1: Inner.m4t1()=2
t2: Inner.m4t2()=2
t1: Inner.m4t1()=1
t2: Inner.m4t2()=1
t1: Inner.m4t1()=0
t2: Inner.m4t2()=0
现在在Inner.m4t2()前面加上synchronized:
private synchronized void m4t2(){
int i= 5;
while(i--> 0){
System.out.println(Thread.currentThread().getName()+": Inner.m4t2()="+ i);
try{
Thread.sleep(500);
} catch(InterruptedException ie){
}
}
}
结果:
尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁,所以t2对Inner.m4t2()的访问也被阻塞,因为m4t2()是Inner中的一个同步方法。
t1: Inner.m4t1()=4
t1: Inner.m4t1()=3
t1: Inner.m4t1()=2
t1: Inner.m4t1()=1
t1: Inner.m4t1()=0
t2: Inner.m4t2()=4
t2: Inner.m4t2()=3
t2: Inner.m4t2()=2
t2: Inner.m4t2()=1
t2: Inner.m4t2()=0
第二篇:
synchronized关键字,它包括两种用法:synchronized方法和 synchronized块。
1. synchronized方法:通过在方法声明中加入 synchronized关键字来声明 synchronized方法。如:
public synchronized void accessVal(int newVal);
synchronized方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized方法都必须获得调用该方法的类实例的锁方能
执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行
状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized的成员函数中至多只有一个处于可执行状态(因为至多只有
一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)
。
在 Java中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized,以控制其对类的静态成
员变量的访问。
synchronized方法的缺陷:若将一个大的方法声明为synchronized将会大大影响效率,典型地,若将线程类的方法 run()声明为
synchronized,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized方法的调用都永远不会成功。当然我们可
以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized,并在主方法中调用来解决这一问题,但是 Java为我们提供
了更好的解决办法,那就是 synchronized块。
2. synchronized块:通过 synchronized关键字来声明synchronized块。语法如下:
synchronized(syncObject){
//允许访问控制的代码
}
synchronized块是这样一个代码块,其中的代码必须获得对象 syncObject(如前所述,可以是类实例或类)的锁方能执行,具体机
制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
对synchronized(this)的一些理解
一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线
程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized
(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)
同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个
object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用
http://hi.baidu.com/sunshibing/blog/item/5235b9b731d48ff430add14a.html
java中synchronized用法
打个比方:一个object就像一个大房子,大门永远打开。房子里有很多房间(也就是方法)。
这些房间有上锁的(synchronized方法),和不上锁之分(普通方法)。房门口放着一把钥匙(key),这把钥匙可以打开所有上锁的房间。
另外我把所有想调用该对象方法的线程比喻成想进入这房子某个房间的人。所有的东西就这么多了,下面我们看看这些东西之间如何作用的。
在此我们先来明确一下我们的前提条件。该对象至少有一个synchronized方法,否则这个key还有啥意义。当然也就不会有我们的这个主题了。
一个人想进入某间上了锁的房间,他来到房子门口,看见钥匙在那儿(说明暂时还没有其他人要使用上锁的房间)。于是他走上去拿到了钥匙
,并且按照自己的计划使用那些房间。注意一点,他每次使用完一次上锁的房间后会马上把钥匙还回去。即使他要连续使用两间上锁的房间,
中间他也要把钥匙还回去,再取回来。
因此,普通情况下钥匙的使用原则是:“随用随借,用完即还。”
这时其他人可以不受限制的使用那些不上锁的房间,一个人用一间可以,两个人用一间也可以,没限制。但是如果当某个人想要进入上锁的房
间,他就要跑到大门口去看看了。有钥匙当然拿了就走,没有的话,就只能等了。
要是很多人在等这把钥匙,等钥匙还回来以后,谁会优先得到钥匙?Not guaranteed。象前面例子里那个想连续使用两个上锁房间的家伙,他
中间还钥匙的时候如果还有其他人在等钥匙,那么没有任何保证这家伙能再次拿到。(JAVA规范在很多地方都明确说明不保证,象
Thread.sleep()休息后多久会返回运行,相同优先权的线程那个首先被执行,当要访问对象的锁被释放后处于等待池的多个线程哪个会优先得
到,等等。我想最终的决定权是在JVM,之所以不保证,就是因为JVM在做出上述决定的时候,绝不是简简单单根据一个条件来做出判断,而是
根据很多条。而由于判断条件太多,如果说出来可能会影响JAVA的推广,也可能是因为知识产权保护的原因吧。SUN给了个不保证就混过去了
。无可厚非。但我相信这些不确定,并非完全不确定。因为计算机这东西本身就是按指令运行的。即使看起来很随机的现象,其实都是有规律
可寻。学过计算机的都知道,计算机里随机数的学名是伪随机数,是人运用一定的方法写出来的,看上去随机罢了。另外,或许是因为要想弄
的确定太费事,也没多大意义,所以不确定就不确定了吧。)
再来看看同步代码块。和同步方法有小小的不同。
1.从尺寸上讲,同步代码块比同步方法小。你可以把同步代码块看成是没上锁房间里的一块用带锁的屏风隔开的空间。
2.同步代码块还可以人为的指定获得某个其它对象的key。就像是指定用哪一把钥匙才能开这个屏风的锁,你可以用本房的钥匙;你也可以指定
用另一个房子的钥匙才能开,这样的话,你要跑到另一栋房子那儿把那个钥匙拿来,并用那个房子的钥匙来打开这个房子的带锁的屏风。
记住你获得的那另一栋房子的钥匙,并不影响其他人进入那栋房子没有锁的房间。
为什么要使用同步代码块呢?我想应该是这样的:首先对程序来讲同步的部分很影响运行效率,而一个方法通常是先创建一些局部变
量,再对这些变量做一些操作,如运算,显示等等;而同步所覆盖的代码越多,对效率的影响就越严重。因此我们通常尽量缩小其影响范围。
如何做?同步代码块。我们只把一个方法中该同步的地方同步,比如运算。
另外,同步代码块可以指定钥匙这一特点有个额外的好处,是可以在一定时期内霸占某个对象的key。还记得前面说过普通情况下钥
匙的使用原则吗。现在不是普通情况了。你所取得的那把钥匙不是永远不还,而是在退出同步代码块时才还。
还用前面那个想连续用两个上锁房间的家伙打比方。怎样才能在用完一间以后,继续使用另一间呢。用同步代码块吧。先创建另外
一个线程,做一个同步代码块,把那个代码块的锁指向这个房子的钥匙。然后启动那个线程。只要你能在进入那个代码块时抓到这房子的钥匙
,你就可以一直保留到退出那个代码块。也就是说你甚至可以对本房内所有上锁的房间遍历,甚至再sleep(10*60*1000),而房门口却还有
1000个线程在等这把钥匙呢。很过瘾吧。
在此对sleep()方法和钥匙的关联性讲一下。一个线程在拿到key后,且没有完成同步的内容时,如果被强制sleep()了,那key还一
直在它那儿。直到它再次运行,做完所有同步内容,才会归还key。记住,那家伙只是干活干累了,去休息一下,他并没干完他要干的事。为
了避免别人进入那个房间把里面搞的一团糟,即使在睡觉的时候他也要把那唯一的钥匙戴在身上。
最后,也许有人会问,为什么要一把钥匙通开,而不是一个钥匙一个门呢?我想这纯粹是因为复杂性问题。一个钥匙一个门当然更
安全,但是会牵扯好多问题。钥匙的产生,保管,获得,归还等等。其复杂性有可能随同步方法的增加呈几何级数增加,严重影响效率。这也
算是一个权衡的问题吧。为了增加一点点安全性,导致效率大大降低,是多么不可取啊。
synchronized的一个简单例子
public class TextThread{
public static void main(String[] args){
TxtThread tt= new TxtThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
class TxtThread implements Runnable{
int num= 100;
String str= new String();
public void run(){
synchronized(str){
while(num> 0){
try{
Thread.sleep(1);
} catch(Exception e){
e.getMessage();
}
System.out.println(Thread.currentThread().getName()
+"this is"+ num--);
}
}
}
}
上面的例子中为了制造一个时间差,也就是出错的机会,使用了Thread.sleep(10)
Java对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步问题。到底如
何?――还得对synchronized关键字的作用进行深入了解才可定论。
总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,
synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。
在进一步阐述之前,我们需要明确几点:
A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其
他线程的对象访问。
B.每个对象只有一个锁(lock)与之相关联。
C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
接着来讨论synchronized用到不同地方对代码产生的影响:
假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都可以调用它们。
1.把synchronized当作函数修饰符时,示例代码如下:
Public synchronized void methodAAA()
{
//….
}
这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中
执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了
synchronized关键字的方法。
上边的示例代码等同于如下代码:
public void methodAAA()
{
synchronized(this)//(1)
{
//…..
}
}
(1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个
拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造
成数据混乱:(
2.同步块,示例代码如下:
public void method3(SomeObject so)
{
synchronized(so)
{
//…..
}
}
这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明
确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:
class Foo implements Runnable
{
private byte[] lock= new byte[0];//特殊的instance变量
Public void methodA()
{
synchronized(lock){//…}
}
//…..
}
注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock
= new Object()则需要7行操作码。
3.将synchronized作用于static函数,示例代码如下:
Class Foo
{
public synchronized static void methodAAA()//同步的static函数
{
//….
}
public void methodBBB()
{
synchronized(Foo.class)// class literal(类名称字面常量)
}
}
代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这
个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。
记得在《Effective Java》一书中看到过将 Foo.class和 P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的
目的。P1指的是由Foo类产生的对象。
可以推断:如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized的instance函数B,那么这个类的同一对象Obj
在多线程中分别访问A和B两个方法时,不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。
小结如下:
搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。
还有一些技巧可以让我们对共享资源的同步访问更加安全:
1.定义private的instance变量+它的 get方法,而不要定义public/protected的instance变量。如果将变量定义为public,对象在外界可以
绕过同步方法的控制而直接取得它,并改动它。这也是JavaBean的标准实现方式之一。
2.如果instance变量是一个对象,如数组或ArrayList什么的,那上述方法仍然不安全,因为当外界对象通过get方法拿到这个instance对象
的引用后,又将其指向另一个对象,那么这个private变量也就变了,岂不是很危险。这个时候就需要将get方法也加上synchronized同步,并
且,只返回这个private对象的clone()――这样,调用端得到的就是对象副本的引用了
java线程同步问题
首先,你如果要线程同步的话,那么需要用关键字去定义。你如果不去定义让线程同步的话,那么线程永远都是串行的,因为每个时间片段只会执行一部分
Java线程:线程的同步-同步方法
线程的同步是保证多线程安全访问竞争资源的一种手段。
线程的同步是Java多线程编程的难点,往往开发者搞不清楚什么是竞争资源、什么时候需要考虑同步,怎么同步等等问题,当然,这些问题没有很明确的答案,但有些原则问题需要考虑,是否有竞争资源被同时改动的问题?
在本文之前,请参阅《Java线程:线程的同步与锁》,本文是在此基础上所写的。
对于同步,在具体的Java代码中需要完成一下两个操作:
把竞争访问的资源标识为private;
同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。
当然这不是唯一控制并发安全的途径。
synchronized关键字使用说明
synchronized只能标记非抽象的方法,不能标识成员变量。
为了演示同步方法的使用,构建了一个信用卡账户,起初信用额为100w,然后模拟透支、存款等多个操作。显然银行账户User对象是个竞争资源,而多个并发操作的是账户方法oper(int x),当然应该在此方法上加上同步,并将账户的余额设为私有变量,禁止直接访问。
/**
* Java线程:线程的同步
*
*@author leizhimin 2009-11-4 11:23:32
*/
public class Test{
public static void main(String[] args){
User u= new User("张三", 100);
MyThread t1= new MyThread("线程A", u, 20);
MyThread t2= new MyThread("线程B", u,-60);
MyThread t3= new MyThread("线程C", u,-80);
MyThread t4= new MyThread("线程D", u,-30);
MyThread t5= new MyThread("线程E", u, 32);
MyThread t6= new MyThread("线程F", u, 21);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
}
}
class MyThread extends Thread{
private User u;
private int y= 0;
MyThread(String name, User u, int y){
super(name);
this.u= u;
this.y= y;
}
public void run(){
u.oper(y);
}
}
class User{
private String code;
private int cash;
User(String code, int cash){
this.code= code;
this.cash= cash;
}
public String getCode(){
return code;
}
public void setCode(String code){
this.code= code;
}
/**
*业务方法
*@param x添加x万元
*/
public synchronized void oper(int x){
try{
Thread.sleep(10L);
this.cash+= x;
System.out.println(Thread.currentThread().getName()+"运行结束,增加“"+ x+"”,当前用户账户余额为:"+ cash);
Thread.sleep(10L);
} catch(InterruptedException e){
e.printStackTrace();
}
}
@Override
public String toString(){
return"User{"+
"code='"+ code+'\''+
", cash="+ cash+
'}';
}
}
输出结果:
线程A运行结束,增加“20”,当前用户账户余额为:120
线程F运行结束,增加“21”,当前用户账户余额为:141
线程E运行结束,增加“32”,当前用户账户余额为:173
线程C运行结束,增加“-80”,当前用户账户余额为:93
线程B运行结束,增加“-60”,当前用户账户余额为:33
线程D运行结束,增加“-30”,当前用户账户余额为:3
Process finished with exit code 0
反面教材,不同步的情况,也就是去掉oper(int x)方法的synchronized修饰符,然后运行程序,结果如下:
线程A运行结束,增加“20”,当前用户账户余额为:61
线程D运行结束,增加“-30”,当前用户账户余额为:63
线程B运行结束,增加“-60”,当前用户账户余额为:3
线程F运行结束,增加“21”,当前用户账户余额为:61
线程E运行结束,增加“32”,当前用户账户余额为:93
线程C运行结束,增加“-80”,当前用户账户余额为:61
Process finished with exit code 0
很显然,上面的结果是错误的,导致错误的原因是多个线程并发访问了竞争资源u,并对u的属性做了改动。
可见同步的重要性。
注意:
通过前文可知,线程退出同步方法时将释放掉方法所属对象的锁,但还应该注意的是,同步方法中还可以使用特定的方法对线程进行调度。这些方法来自于java.lang.Object类。
void notify()
唤醒在此对象监视器上等待的单个线程。
void notifyAll()
唤醒在此对象监视器上等待的所有线程。
void wait()
导致当前的线程等待,直到其他线程调用此对象的 notify()方法或 notifyAll()方法。
void wait(long timeout)
导致当前的线程等待,直到其他线程调用此对象的 notify()方法或 notifyAll()方法,或者超过指定的时间量。
void wait(long timeout, int nanos)
导致当前的线程等待,直到其他线程调用此对象的 notify()方法或 notifyAll()方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。
java 多核处理器下会发生同时获取对象锁的情况吗
对象锁类锁
对象锁
当一个对象中有synchronized method或synchronized block的时候调用此对象的同步方法或进入其同步区域时,就必须先获得对象锁。如果此对象的对象锁已被其他调用者占用,则需要等待此锁被释放
同步静态方法/静态变量互斥体
由于一个class不论被实例化多少次,其中的静态方法和静态变量在内存中都只由一份。所以,一旦一个静态的方法被申明为synchronized。此类所有的实例化对象在调用此方法,共用同一把锁,我们称之为类锁。一旦一个静态变量被作为synchronized block的mutex。进入此同步区域时,都要先获得此静态变量的对象锁
类锁
由上述同步静态方法引申出一个概念,那就是类锁。其实系统中并不存在什么类锁。当一个同步静态方法被调用时,系统获取的其实就是代表该类的类对象的对象锁
在程序中获取类锁
可以尝试用以下方式获取类锁
synchronized(xxx.class){}
synchronized(Class.forName("xxx")){}
同时获取2类锁
同时获取类锁和对象锁是允许的,并不会产生任何问题,但使用类锁时一定要注意,一旦产生类锁的嵌套获取的话,就会产生死锁,因为每个class在内存中都只能生成一个Class实例对象。
关于java同步锁用什么释放和java线程同步问题的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。