synchronized (this)和synchronized (object)区别?请java多线程高手帮忙解决。

zhaolh2002 2009-03-31 10:38:34
下面自己写的帐号转账的例子,用synchronized (this)没有问题,用synchronized (object)就报java.lang.IllegalMonitorStateException: current thread not owner。
并且这个object是从外边传入应该是一个对象,为什么还报这个错误。

代码分别如下:
并发访问安全的SyncAccount.java

package com.thread.account;

import java.util.Arrays;

public class SyncAccount {
public static final double SUM_NUM = 10000;
public static final int ACCOUNT_NUM = 10;
public static final double ACCOUNT_ININ = SUM_NUM / ACCOUNT_NUM;
private double[] account;

private Object lock;
//private final Object lock = new Object();// 采用this替代

public SyncAccount(double initAmount,Object lock) {
this.lock=lock;

account = new double[ACCOUNT_NUM];
for (int i = 0; i < ACCOUNT_NUM; i++) {
account[i] = initAmount;
}
}

public boolean checkFrom(int from, double transMoney) {
//synchronized (this) {
synchronized (lock) {
return account[from] >= transMoney;
}
}

public void print(String prompt) {
//synchronized (this) {
synchronized (lock) {
System.out
.println(prompt + "Arrays={" + Arrays.toString(account) + "}");
}
}

public boolean checkSum() {
double sum = 0;

//synchronized (this) {
synchronized (lock) {

for (int i = 0; i < ACCOUNT_NUM; i++) {
sum = account[i] + sum;
}
}

return sum == SUM_NUM;
}

public int SyncTransform(int from, int to, double transMoney)
throws InterruptedException {
int result = 0;

//synchronized (this) {
synchronized (lock) {
String threadName = "Thread=" + Thread.currentThread().getName()
+ ",";
System.out.println(threadName + "lock=" + lock.hashCode());
System.out.println(threadName + "AccountFrom=" + from);
System.out.println(threadName + "AccountTo=" + to);
System.out.println(threadName + "Account[From]=" + account[from]);
System.out.println(threadName + "transMoney=" + transMoney);
print(threadName + "before trans:");

while (account[from] < transMoney) {// if的惯用法
System.out.println("in wait()");
wait();
}

account[from] = account[from] - transMoney;
account[to] = account[to] + transMoney;
System.out.println(threadName + "check sum=" + checkSum());
System.out.println(threadName + "notify all!");
print(threadName + "after trans:");
notifyAll();

return result;
}
}

}


封装成多线程的SyncAccoutManager.java

package com.thread.account;

public class SyncAccoutManager implements Runnable {

private SyncAccount acc;
private int transFrom;

public SyncAccoutManager(SyncAccount acc,int transFrom) {
this.acc = acc;
this.transFrom=transFrom;
}

public SyncAccoutManager(SyncAccount acc) {
this.acc = acc;
this.transFrom=0;
}

// 客户端启动多线程,系统自动调用类的run方法
public void run() {
try {
while (true) {

double transMoney = SyncAccount.ACCOUNT_ININ * Math.random();
int transTo=(int)(SyncAccount.ACCOUNT_NUM *Math.random());

acc.SyncTransform(transFrom,transTo,transMoney);
Thread.sleep((long)(100*Math.random()));
}
} catch (InterruptedException e) {
System.out.println("error-------");
e.printStackTrace();
}

}

}


测试客户端的MutiThreadClient.java

...全文
775 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Miracle1216 2009-04-08
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 fuyou001 的回复:]
引用 6 楼 zhaolh2002 的回复:
那位达人告诉我程序应该怎么才可以使用synchronized (object),我这边如果定义成final是没有问题的的。
一定送上50分。

当你要同步时,可以设置一个类成员变量,然后用synchronized (object)
但要注意4楼给的提示

简单点有
class A{
private final Object lock = new Object();/
public void method(){
synchronized (lock){ //保证 同步
}

}

}
[/Quote]

你不是说设置一个类成员变量吗,怎么变成final的了。我知道类变量是可以的,不知道为什么final的也可以,请指点。
fuyou001 2009-04-08
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 zhaolh2002 的回复:]
那位达人告诉我程序应该怎么才可以使用synchronized (object),我这边如果定义成final是没有问题的的。
一定送上50分。
[/Quote]
当你要同步时,可以设置一个类成员变量,然后用synchronized (object)
但要注意4楼给的提示

简单点有
class A{
private final Object lock = new Object();/
public void method(){
synchronized (lock){ //保证 同步
}

}

}
yinglu206 2009-04-08
  • 打赏
  • 举报
回复
mark
oklinsong 2009-04-01
  • 打赏
  • 举报
回复
顶一下!
zhaolh2002 2009-04-01
  • 打赏
  • 举报
回复
那位达人告诉我程序应该怎么才可以使用synchronized (object),我这边如果定义成final是没有问题的的。
一定送上50分。
happy84911 2009-04-01
  • 打赏
  • 举报
回复
顶起
ZiSheng 2009-04-01
  • 打赏
  • 举报
回复

原因很简单,你没有获得对象锁的情况下,是不允许调用该对象的wait,notify,sleep这些函数的,
在你的例子里边,你获得了lock的对象锁,却调用了this的wait,notify,所以会报错。
  • 打赏
  • 举报
回复
wait();notifyAll();
此方法只应由作为此对象监视器的所有者的线程来调用
而线程只锁住了lock 没有锁住this
用lock.wait() lock.notifyAll();
zhaolh2002 2009-03-31
  • 打赏
  • 举报
回复
不好意思,忘记发测试客户端代码MutiThreadClient.java:



package com.thread.account;

public class MutiThreadClient {
public static void main(String[] args) {
double initAmount=SyncAccount.ACCOUNT_ININ;
Object lock=new int[0];
SyncAccount acc=new SyncAccount(initAmount,lock);


for (int i = 0; i < SyncAccount.ACCOUNT_NUM; i++) {
SyncAccoutManager syncAcc=new SyncAccoutManager(acc,i);
Thread t= new Thread(syncAcc);
t.start();
}
}
}

62,614

社区成员

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

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