Java的线程同步问题-synchronized

零起跑线 2010-03-24 07:52:28
还没用过java的多线程,但在《操作系统》中学过线程的同步,了解一些互斥的问题
现在看到了一段java程序,其中用到了synchronized关键字,知道是用于线程间同步的,但不知道具体的使用方法,
在网上查了一些资料,知道synchronized可以用在方法前,只要在方法前加上synchronized关键字就行了
但是看到这样几种写法,不知道怎么解释,求解:

//写法1
public class implements Runable{
...
String str = new String();
public void run{
...
synchronized(str){
...
}
...
}
...
}

//写法2
public class Test{
...
synchronized(Test.class){
...
}
...
}



顺便再问一个问题:

//下面的两个引用str和str1是不是指向同一个对象
String str = new String();
String str1 = str;

//下面的两个引用是不是指向了不同的对象
String str = "abc";
String str1 = "abc";


如何判断两个引用是否是指向同一个对象,有什么方法可以判断
...全文
158 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
无伤 2010-03-24
  • 打赏
  • 举报
回复
第二个问题都是指向同一个对象, Java 对String做了优化,引入了String池, 如果多个变量的值一样, 那他们实际指向的是同一个对象。
零起跑线 2010-03-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 fatroach 的回复:]
你就这样理解,被synchronized保护的代码块,同时只能有一个线程在执行
[/Quote]

这样的确很容易理解。。。
afunx 2010-03-24
  • 打赏
  • 举报
回复
关于String对象,在建立的时候,如果已经存在了,则引用同一个地址:
比如,String str1 = "abc";String str2 = "abc";
若String str2 = "aba";则不同,好像有个术语叫“什么池的”,不太记得了。
synchronized就是指该线程在执行时,不能中断。必须得该线程执行结束才能执行其他线程。
比如synchronized A{1;2;3},synchronized B{1;2;3}
则执行的时候可能是:A{1;2;3} B{1;2;3} B{1;2;3} A{1;2;3}
而如果没有的话,很可能A{1;2}B{1}A{3}B{2;3}B{1;2;3}A{1}B{1}A{2;3}B{2;3}
不知道这样解释,是否好理解一些呢?

fatRoach 2010-03-24
  • 打赏
  • 举报
回复
你就这样理解,被synchronized保护的代码块,同时只能有一个线程在执行
so185582 2010-03-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 blvyoucan 的回复:]
引用 2 楼 so185582 的回复:
对象的hashCode方法可以判断


用了以下方法进行了测试

Java code

package test;

public class Test1{
public static void main(String[] args){
String str = "abc";
String ……
[/Quote]

运行结果没问题,前三个都是同一个对象.
相同的"abc"只存在一个,str和str2引用的都是同一个对象
零起跑线 2010-03-24
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 peiqu123 的回复:]
synchronized还有第三种用法:

Java code

public synchronized void run()
{.....}


这种用法表明在一个时刻只能有一个对象调用该方法。
而你自己列出的两种是用对象作为锁,我们都知道在访问临界区资源时,要加锁,退出时再解锁;
而java里可以对对象的引用加锁,synchronized(o)中的o是一个对象的引用,线程……
[/Quote]

谢谢你,关于String对象应该是明白了,但是synchronized还不是太了解
零起跑线 2010-03-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 blvyoucan 的回复:]
引用 2 楼 so185582 的回复:
对象的hashCode方法可以判断


用了以下方法进行了测试

Java code

package test;

public class Test1{
public static void main(String[] args){
String str = "abc";
String ……
[/Quote]

或者我应该问,怎么才能建立两个值一样的String对象
零起跑线 2010-03-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 so185582 的回复:]
对象的hashCode方法可以判断
[/Quote]

用了以下方法进行了测试

package test;

public class Test1{
public static void main(String[] args){
String str = "abc";
String str1 = str;
String str2 = "abc";
String str3 = "abcd";
String str4 = "abce";
System.out.println(str.hashCode());
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());
System.out.println(str3.hashCode());
System.out.println(str4.hashCode());
}
}


运行结果一直是

96354
96354
96354
2987074
2987075

对str和str2,感觉应该是两个对象,是不是java对其进行了优化处理
peiqu123 2010-03-24
  • 打赏
  • 举报
回复
synchronized还有第三种用法:

public synchronized void run()
{.....}

这种用法表明在一个时刻只能有一个对象调用该方法。
而你自己列出的两种是用对象作为锁,我们都知道在访问临界区资源时,要加锁,退出时再解锁;
而java里可以对对象的引用加锁,synchronized(o)中的o是一个对象的引用,线程在访问临界区资源时,会先访问对象o,如果此时o没有其他线程被加锁,则可以访问临界区资源,反之则等到该对象被解锁后才能访问。

而下个问题,我先告诉你两种都指向了同一个对象,第一种new String()产生了对象s,而引用str指向了它,然后str1再指向了str,也就是指向了对象s。第二种:由于字符串常量是存储在池里的,当有新的字符串出现时,虚拟机将在池里寻找有无相同的字符串常量,若无,则生成新的对象,反之,则不会生成新的对象。所以两个引用str和str1都指向了池里的字符串常量。字符串也是一个对象。也可以调用String类中的方法。

如果你想真正了解引用和对象的关系,先要关注它们如何存储在内存中的。
afunx 2010-03-24
  • 打赏
  • 举报
回复
synchronized是用在线程完整性的。比如线程A,B;如果未用synchronized,则可能线程A运行到一半时,运行线程B;
比如一个银行数据库系统。A是取钱的,B是检查所取的钱是否大于存款的。
A{B,如果可以取钱,账户减去所取金额}B{判断要取的钱是否大于存款}
A1{B}A2{B}A1{取钱,账户更新}A2{取钱,账户更新}这样的话,存款就变成负的了。
不知道表达得是否清楚。

第二个问题,第一个肯定是指向同一个对象的。第二个好像也是吧,以前好像看过类似的问题,不过由于不太关注细节,也不是非常确定。待高人指点。
so185582 2010-03-24
  • 打赏
  • 举报
回复
对象的hashCode方法可以判断
so185582 2010-03-24
  • 打赏
  • 举报
回复
同步块,作用差不多的.synchronized(str)是以str对象作为锁资源.synchronized(Test.class)是以Test类型作为锁资源.

第二题指向的都是向一个对象

62,614

社区成员

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

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