给个同步块(synchorized block)的解释

yhcdio 2010-05-14 12:53:41
我翻了2天书,还是没搞明白synchorized(对象){}这个是什么意思= =。
线程同步有两种: synchorized method 和 synchorized block
synchorized method 相当于 synchorized (this)
这个this要是换成object我就不懂了。。。 怎么解释,请给位大虾赐教。最好附上例子。
...全文
307 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
在同步块前面加些代码那当然是不一样的了。
qybao 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 bao110908 的回复:]
引用 2 楼 qybao 的回复:
synchorized method 和 synchorized (this)是不完全等价的
synchorized(对象)是锁对象,如果要释放对象的锁,就要调用 对象.notify或对象.notifyAll,同样的,其他线程要发生等待,就要调用 对象.wait,synchorized (this)是一种特殊的synchorized(对象),this是对象自……
[/Quote]
synchronized method 与 sychronized(this) 包住整个方法,从结果来说是一样的,但是从锁角度来说是不一样的,sychronized(this)的时候 ,可以多个线程同时进入方法,在sychronized(this)的地方发生等待,如果sychronized(this)之前有别的处理代码,结果可能就不一样了
小例子,自己体会一下吧

class A {
String zz = "start";
Object obj = new Object(); //用于锁的对象
public synchrinized void synSetZZ(String z) { //这里是锁方法
try {
for (int i=0; i<10; i++) {
System.out.println(Thread.currentThread().getName()+ "->" + i);
Thread.sleep();
}
} catch (Throwable e) {
e.printStackTrace();
}
zz = z;
System.out.println(Thread.currentThread().getName()+ "->" + zz);
}

public void setZZ(String z) {
try {
for (int i=0; i<10; i++) {
System.out.println(Thread.currentThread().getName()+ "->" + i);
Thread.sleep();
}
} catch (Throwable e) {
e.printStackTrace();
}

//为了说明synchronized method 跟syncronized(this)不一样,在前面加入了上面的代码
//可以知道,在synchronized(this)之前,多个线程可以同时进入方法
synchronized(this) { //这里是锁自己
zz = z;
System.out.println(Thread.currentThread().getName() + "->" + zz);
}
}

public void synObjSetZZ(String z) {
synchronized(obj) { //这里是锁obj
try {
for (int i=0; i<10; i++) {
System.out.println(Thread.currentThread().getName()+ "->" + i);
Thread.sleep();
}
} catch (Throwable e) {
e.printStackTrace();
}

zz = z;
System.out.println(Thread.currentThread().getName() + "->" + zz);
}
}
}

class B implements Runnable {
public static int runMode = 1;
A a;
public B (A a) {
this.a = a;
}
public void run () {
if (runMode == 1) {
a.synSetZZ("Mode:" + 1);
} else if (runMode == 2) {
a.setZZ("Mode:" + 2);
} else {
a.synObjSetZZ("Mode:" + 3);
}
}
}

public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B(a);
System.out.println("--------Mode 1-----------");
Thread t1 = new Thread(b);
Thread t2 = new Thread(b);
t1.start();
t2.start();

System.out.println("--------Mode 2-----------");
B.runMode = 2;
t1 = new Thread(b);
t2 = new Thread(b);
t1.start();
t2.start();

System.out.println("--------Mode 3-----------");
B.runMode = 3;
t1 = new Thread(b);
t2 = new Thread(b);
t1.start();
t2.start();
}
}



yhcdio 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 soli11722984 的回复:]
就是拿XXX作为锁来代替this(自己)作为锁,因为一个实例里可能有N个方法需要同步,要是都拿自己作为锁,可能会效率很差,那时就多拿几个XXX代替this,那就可以变成一个实例只有特定的方法才需要同一个锁,其他方法可以用其他的锁或不用,这样效率会高很多
[/Quote]

哦 原来如此 写过高手了~
结贴给分
dracularking 2010-05-14
  • 打赏
  • 举报
回复
this不是对象吗?

每一个对象都有一个Intrinsic Lock

Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.

Intrinsic Lock两个功能:强制对象的互斥访问和建立对可见性有重要影响的happens-before关系
比如围绕同一个锁,某线程a的释放锁就是happens-before某线程b的获得锁
soli11722984 2010-05-14
  • 打赏
  • 举报
回复
就是拿XXX作为锁来代替this(自己)作为锁,因为一个实例里可能有N个方法需要同步,要是都拿自己作为锁,可能会效率很差,那时就多拿几个XXX代替this,那就可以变成一个实例只有特定的方法才需要同一个锁,其他方法可以用其他的锁或不用,这样效率会高很多
yhcdio 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 soli11722984 的回复:]
Java code

//这个上面的,我稍微改了点,和修正了些语法错误
class C {

private String zz = "Nothing happend";
private Object obj = new Object();

public String getString() {
return zz;
}

……
[/Quote]
恩 刚看到你改的 呵呵
那就算是改成object 这有啥用? 我就搞不清楚 object 算在那干嘛地 ,难道他就提供一个锁,实现个同步,然后什么也不管了?那我直接用(this)不完了,
yhcdio 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 soli11722984 的回复:]
引用 4 楼 yhcdio 的回复:
引用 3 楼 soli11722984 的回复:
JAVA的同步机制是由锁来控制
要是换成了obj(也就是别的对象),那么当进入了方法体的synchorized (obj),那么程序就会去找obj指向的实例是否已经给别的synchorized (obj)拿去了(意思就是说有米别的方法体需要用到这个对象作为锁),如果没有别的方法体synchorized (……
[/Quote]

那我还有个疑问,synchorized(XXX)中的XXX有什么用?
如果是(this)我觉得还能理解,线程在竞争一个资源(zz)。但是现在线程竞争又跟XXX的对象扯上关系了?能否给个事务例子说明一下
soli11722984 2010-05-14
  • 打赏
  • 举报
回复

//这个上面的,我稍微改了点,和修正了些语法错误
class C {

private String zz = "Nothing happend";
private Object obj = new Object();

public String getString() {
return zz;
}

public void setString() {
synchronized (obj) {
zz = Thread.currentThread().getName() + " change its context!";
System.out.println(zz);
}
}
}

public class Test implements Runnable {
private C c = new C();
public static void main(String[] args) {

Test a = new Test();

Thread one = new Thread(a);
Thread two = new Thread(a);

one.setName("OneThread");
two.setName("TwoThread");

one.start();
two.start();
}

public void run() {
for (int i = 0; i < 10; i++) {
c.setString();
}
}
}



//这个是输出
OneThread change its context!
TwoThread change its context!
OneThread change its context!
TwoThread change its context!
OneThread change its context!
TwoThread change its context!
TwoThread change its context!
TwoThread change its context!
TwoThread change its context!
TwoThread change its context!
TwoThread change its context!
OneThread change its context!
TwoThread change its context!
OneThread change its context!
TwoThread change its context!
OneThread change its context!
OneThread change its context!
OneThread change its context!
OneThread change its context!
OneThread change its context!


不过以上的可能不是你想要的,所以我写成这样

class C {

private String zz = "Nothing happend";
private Object obj = new Object();

public String getString() {
return zz;
}

public void setString() {
synchronized (obj) {
for (int i = 0; i < 10; i++) {
zz = Thread.currentThread().getName() + " change its context!";
System.out.println(zz);
}
}
}
}

public class Test implements Runnable {
private C c = new C();

public static void main(String[] args) {

Test a = new Test();

Thread one = new Thread(a);
Thread two = new Thread(a);

one.setName("OneThread");
two.setName("TwoThread");

one.start();
two.start();
}

public void run() {

c.setString();

}
}
soli11722984 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 yhcdio 的回复:]
引用 3 楼 soli11722984 的回复:
JAVA的同步机制是由锁来控制
要是换成了obj(也就是别的对象),那么当进入了方法体的synchorized (obj),那么程序就会去找obj指向的实例是否已经给别的synchorized (obj)拿去了(意思就是说有米别的方法体需要用到这个对象作为锁),如果没有别的方法体synchorized (obj)拿去了,就当前的方法体用作对象锁……
[/Quote]

应该说是进入了,不过只是停在synchorized(obj)这里,因为锁被拿走了,直到obj释放了,才会去竞争锁
yhcdio 2010-05-14
  • 打赏
  • 举报
回复
麻烦 soli11722984看看我写的对不对,不对指出来(最好用代码写个列子)谢谢啦 O(∩_∩)O~
yhcdio 2010-05-14
  • 打赏
  • 举报
回复
麻烦 qybao看看我写的对不对,不对指出来(最好用代码写个列子)谢谢啦 O(∩_∩)O~
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qybao 的回复:]
synchorized method 和 synchorized (this)是不完全等价的
synchorized(对象)是锁对象,如果要释放对象的锁,就要调用 对象.notify或对象.notifyAll,同样的,其他线程要发生等待,就要调用 对象.wait,synchorized (this)是一种特殊的synchorized(对象),this是对象自己本身,所以this.wait,this.notify等等中的this可以省略,所以直接wait和notify就可以了,实际上,原理是一样的
[/Quote]

synchronized method 与 sychronized(this) 包住整个方法是一致的吧?都是采用当前对象作为监视对象
yhcdio 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 soli11722984 的回复:]
JAVA的同步机制是由锁来控制
要是换成了obj(也就是别的对象),那么当进入了方法体的synchorized (obj),那么程序就会去找obj指向的实例是否已经给别的synchorized (obj)拿去了(意思就是说有米别的方法体需要用到这个对象作为锁),如果没有别的方法体synchorized (obj)拿去了,就当前的方法体用作对象锁,那么要是有别的synchorized (obj)需……
[/Quote]


楼上高手,我根据你的意思写了下面这个(伪代码,手边没有环境)。假如OneThread先进入运行中状态(假如此时TwoThread在可运行状态),是说OneThread取得XXX的对象的锁,然后运行了synchorized块中的代码,而此时由于XXX的锁在OneThread处,所以
TwoThread无法进入?是这个意思吗?


class C {

private String zz = "Nothing happend";

public String getString(){

return zz;

}

public void setString(){

synchorized(XXX){

zz = Thread.currentThread().getName() + "change its context!";

}

}

}


class XXX{
}

public class A implements Runnable{

private C c = new C();

public static void main(String [] args){

A a = new a();

Thread one = new Thread(a);

Thread two= new Thread(a);

one.setName("OneThread");

two.setName("TwoThread");

one.start();

two.start();
}



public void run(){

for(int i=0 ;i<10;<i++)
{
c.setString();
}

}


}
soli11722984 2010-05-14
  • 打赏
  • 举报
回复
JAVA的同步机制是由锁来控制
要是换成了obj(也就是别的对象),那么当进入了方法体的synchorized (obj),那么程序就会去找obj指向的实例是否已经给别的synchorized (obj)拿去了(意思就是说有米别的方法体需要用到这个对象作为锁),如果没有别的方法体synchorized (obj)拿去了,就当前的方法体用作对象锁,那么要是有别的synchorized (obj)需要这个obj,那就等吧,等到释放为止
qybao 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用楼主 yhcdio 的回复:]
我翻了2天书,还是没搞明白synchorized(对象){}这个是什么意思= =。
线程同步有两种: synchorized method 和 synchorized block
synchorized method 相当于 synchorized (this)
这个this要是换成object我就不懂了。。。 怎么解释,请给位大虾赐教。最好附上例子。
[/Quote]
synchorized method 和 synchorized (this)是不完全等价的
synchorized(对象)是锁对象,如果要释放对象的锁,就要调用 对象.notify或对象.notifyAll,同样的,其他线程要发生等待,就要调用 对象.wait,synchorized (this)是一种特殊的synchorized(对象),this是对象自己本身,所以this.wait,this.notify等等中的this可以省略,所以直接wait和notify就可以了,实际上,原理是一样的

62,621

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧