下面自己写的帐号转账的例子,用synchronized (this)没有问题,用synchronized (object)就报java.lang.IllegalMonitorStateException: current thread not owner。
并且这个object是从外边传入应该是一个对象,为什么还报这个错误。代码分别如下:
并发访问安全的SyncAccount.javapackage 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.javapackage 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

解决方案 »

  1.   

    不好意思,忘记发测试客户端代码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();
    }
    }
    }
      

  2.   

    wait();notifyAll();
     此方法只应由作为此对象监视器的所有者的线程来调用
    而线程只锁住了lock 没有锁住this
    用lock.wait() lock.notifyAll();
      

  3.   


    原因很简单,你没有获得对象锁的情况下,是不允许调用该对象的wait,notify,sleep这些函数的,
    在你的例子里边,你获得了lock的对象锁,却调用了this的wait,notify,所以会报错。
      

  4.   

    那位达人告诉我程序应该怎么才可以使用synchronized (object),我这边如果定义成final是没有问题的的。
    一定送上50分。
      

  5.   

    当你要同步时,可以设置一个类成员变量,然后用synchronized (object)
    但要注意4楼给的提示简单点有
    class A{
    private final Object lock = new Object();/
    public void method(){
     synchronized (lock){  //保证 同步
    }}}
      

  6.   


    你不是说设置一个类成员变量吗,怎么变成final的了。我知道类变量是可以的,不知道为什么final的也可以,请指点。