java同步锁怎么判断要对哪个对象上锁?

jchen104 2018-12-26 12:35:06

public class Test {
public static void main(String[] args) {
Account account=new Account(100);
Person p1=new Person(account,80);
Person p2=new Person(account,90);
p1.start();
p2.start();

}
}

class Account{
int total;
public Account(int total) {
super();
this.total=total;
}
}

class Person extends Thread{
private int reduce;
public Account account;
public Person(Account account,int reduce) {

this.account=account;
this.reduce=reduce;
}

public synchronized void run() {
if (account.total-reduce<0) return ;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
account.total-=reduce;
System.out.println(Thread.currentThread().getName()+"取出"+reduce);
System.out.println(Thread.currentThread().getName()+"剩余"+account.total);

}
}

Thread-0取出80
Thread-1取出90
Thread-0剩余-70
Thread-1剩余-70

模仿的账户取钱操作,好像是因为同步锁没锁住account,但是synchronized不是把person对象上锁了吗,
account也是person对象成员啊为什么没锁住?
到底怎么去判断要对哪个对象上锁,怎么判断上锁成功没呢?
...全文
195 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
lkj2016 2018-12-26
  • 打赏
  • 举报
回复
synchronized只锁定对象,每个对象只有一个锁(lock)与之相关联

public synchronized void run() {...}


等价于public void run(
synchronized (this){...}
)

P1和P2的this不是同一个
kampoo 2018-12-26
  • 打赏
  • 举报
回复
从你描述的需求来看,你的代码里需要加锁的是account对象,而不是person对象。修改下(未调试),供参考:
public class Test {
    public static void main(String[] args) {
        Account account=new Account(100);
        Person p1=new Person(account,80);
        Person p2=new Person(account,90);
        p1.start();
        p2.start();
         
    }   
}
 
class Account{
    int total;   
    public Account(int total) {
        super();
        this.total=total;       
    }   
}
 
class Person extends Thread{
    // Abel: 加一个类锁。这种方法很低效,应该把锁加到账户上。这里只是为了指出代码问题。
    private static Object lock = new Object();

    private int reduce;
    public Account account;
    public Person(Account account,int reduce) {
     
        this.account=account;
        this.reduce=reduce;
    }

    // Abel: 改为使用类静态对象lock加锁     
    public void run() {   
      synchronized(lock) {
        if (account.total-reduce<0) return ;
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        account.total-=reduce;
        System.out.println(Thread.currentThread().getName()+"取出"+reduce);
        System.out.println(Thread.currentThread().getName()+"剩余"+account.total);
      }
    }
}

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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