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

yhcdio 2010-05-14 12:53:41
我翻了2天书,还是没搞明白synchorized(对象){}这个是什么意思= =。
线程同步有两种: synchorized method 和 synchorized block
synchorized method 相当于 synchorized (this)
这个this要是换成object我就不懂了。。。 怎么解释,请给位大虾赐教。最好附上例子。
...全文
309 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就可以了,实际上,原理是一样的

代码下载链接: https://pan.quark.cn/s/a4b39357ea24 用户账户控制(UAC)白名单的配置 Windows7环境中 UAC(User Account Control,用户帐户控制)是由微软在Windows Vista版本中推出的一项旨在增强系统安全性的创新技术,该技术强制要求用户在执行可能干扰计算机正常运作的操作或进行更改会波及其他用户设置的变动前,必须提供相应的权限或管理员密码进行验证。通过对这些操作启动前进行授权确认,UAC能够有效阻止恶意软件及间谍软件在未获授权的状态下于计算机内进行安装或实施修改。 自从Vista版本问世以来,微软便开始推行这一全新的安全机制,可视为对系统安全防护的显著提升。尽管UAC确实能够在一定程度上对某些非法程序起到防御作用,但与此同时,这一功能也给众多用户带来了诸多不便。 因此,许多用户开始探寻是否存在类似于白名单的功能,以便将那些值得信赖的程序直接赋予运行权限。事实上,这类功能确实存在,不过微软并未将其作为标准配置提供。 网络上关于此问题的绝大多数建议都是建议禁用UAC,这种说法显然缺乏针对性,因为若用户希望禁用此功能,本就不会提出相关疑问。 通过运用微软官方发布的Microsoft Application Compatibility Toolkit 5.6版本,可以将信任的程序纳入系统白名单范畴。 获取Application Compatibility Toolkit 安装程序成功后会出现三个可执行文件 以管理员身份启动Compatibility Administrator 在Custom DataBases部分创建新的数据库,并添加一个Application Fix(在下方空白处点击右键,选择...

62,620

社区成员

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

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