困扰我两天了, 锁对象打死都锁不住? 求高手解答!! 标题要长.........................

Kanepan 2010-01-07 12:50:25
最近做一个项目,关于锁机制还没弄清楚。
直接看代码吧
为什么C线程调用了对象a的add()方法 但是add()方法中messages明明被锁住了,为什么还能对messages进行增加操作?
搞了半天不解。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SynchronizedTest {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
A a = new A();
B b = new B(a);
C c = new C(a);
es.submit(b);
es.submit(c);
}

}

class A{
private List<Integer> messages = new ArrayList<Integer>();

public void add(int message){
messages.add(message);
}

public List<Integer> getMessages() {
return messages;
}

public void setMessages(List<Integer> messages) {
this.messages = messages;
}

public void dothis(){
synchronized(messages){
try {
System.out.println(messages);
Thread.sleep(4000);
System.out.println("now" + messages);
messages.clear();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

class B implements Runnable{
private A a;
public B(A a){
this.a = a;
}
@Override
public void run() {
System.out.println("start thread b");
a.dothis();
}
}

class C implements Runnable{
private A a;
public C(A a){
this.a = a;
}
@Override
public void run() {
System.out.println("start Thread c");
a.add(1);
a.add(2);
System.out.println("next Thread "+ a.getMessages());
}
}

...全文
194 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
Dazzlingwinter 2010-01-07
  • 打赏
  • 举报
回复

public synchronized void dothis(messages){
try {
Thread.sleep(4000);
System.out.println(messages);
messages.clear();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

改一下,看这样行不?
nihuajie05 2010-01-07
  • 打赏
  • 举报
回复
B执行完了dothis,不就解锁了么?
然后C就执行2步add啊
我不明白楼主纠结所在?
run里面只是线程要执行的序列,不代表该进程要一直跑,跑完了重新跑,再跑。。。

是不是这么一说来着,楼下继续
xinji84 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 nihuajie05 的回复:]
额。。我想说我自己的。。。怎么跑出来这么多人
我去跑过代码了,也分析了原因。有些改动。先代码
Java codeimport java.util.ArrayList;import java.util.List;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;publicclass SynchronizedTest {publicstaticvoid main(String[] args) {
ExecutorService es= Executors.newCachedThreadPool();
A a=new A();
B b=new B(a);
C c=new C(a);
es.submit(b);
es.submit(c);
}

}class A{private List<Integer> messages=new ArrayList<Integer>();publicvoid add(int message){synchronized(messages){
messages.add(message);
}
}public List<Integer> getMessages() {return messages;
}publicvoid setMessages(List<Integer> messages) {this.messages= messages;
}publicvoid dothis(){synchronized(messages){try {
System.out.println(messages);
Thread.sleep(1000);
System.out.println("now"+ messages);
messages.clear();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}class Bimplements Runnable{private A a;public B(A a){this.a= a;
}
@Overridepublicvoid run() {
System.out.println("start thread b");
a.dothis();
}
}class Cimplements Runnable{private A a;public C(A a){this.a= a;
}
@Overridepublicvoid run() {
System.out.println("start Thread c");
a.add(1);
a.add(2);
System.out.println("next Thread"+ a.getMessages());
}
原因很简单,2楼所说的synchronized的使用方法好像也是不行的,同样需要在add方法上添加synchronized
但是呢,Thinking in Java比较推荐的是楼主原先的方法,于是我就按照楼主的方法来改了。
楼主的这种锁的机制在于,只有在使用synchronized的地方才对被synchronized持有的变量进行检测,看是否被其他线程掌握了。
你只有dothis中检测,但是你的C不执行dothis,而是add。。。所以我在add中添加了synchronized语句

楼主可以试下我的代码
[/Quote]

完全正确
Kanepan 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 nihuajie05 的回复:]
我也忘记了。。
平时也不怎么用,当年支付宝招聘的时候还考过。。。还写错了。
[/Quote]

跑过了是可以了,谢谢
liwenso 2010-01-07
  • 打赏
  • 举报
回复
对象锁只在同一个方法中有效
nihuajie05 2010-01-07
  • 打赏
  • 举报
回复
我也忘记了。。
平时也不怎么用,当年支付宝招聘的时候还考过。。。还写错了。
树成 2010-01-07
  • 打赏
  • 举报
回复
一看就知道楼主对多线程和线程同步没概念。
nihuajie05 2010-01-07
  • 打赏
  • 举报
回复
额。。我想说我自己的。。。怎么跑出来这么多人
我去跑过代码了,也分析了原因。有些改动。先代码

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class SynchronizedTest {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
A a = new A();
B b = new B(a);
C c = new C(a);
es.submit(b);
es.submit(c);
}

}

class A{
private List<Integer> messages = new ArrayList<Integer>();

public void add(int message){
synchronized(messages){
messages.add(message);
}
}

public List<Integer> getMessages() {
return messages;
}

public void setMessages(List<Integer> messages) {
this.messages = messages;
}

public void dothis(){
synchronized(messages){
try {
System.out.println(messages);
Thread.sleep(1000);
System.out.println("now" + messages);
messages.clear();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

class B implements Runnable{
private A a;
public B(A a){
this.a = a;
}
@Override
public void run() {
System.out.println("start thread b");
a.dothis();
}
}

class C implements Runnable{
private A a;
public C(A a){
this.a = a;
}
@Override
public void run() {
System.out.println("start Thread c");
a.add(1);
a.add(2);
System.out.println("next Thread "+ a.getMessages());
}


原因很简单,2楼所说的synchronized的使用方法好像也是不行的,同样需要在add方法上添加synchronized
但是呢,Thinking in Java比较推荐的是楼主原先的方法,于是我就按照楼主的方法来改了。
楼主的这种锁的机制在于,只有在使用synchronized的地方才对被synchronized持有的变量进行检测,看是否被其他线程掌握了。
你只有dothis中检测,但是你的C不执行dothis,而是add。。。所以我在add中添加了synchronized语句

楼主可以试下我的代码
Kanepan 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 nihuajie05 的回复:]
ls犯2了,大家躲让
[/Quote]

真能了解清楚,我多2几次都没关系
Kanepan 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 dazzlingwinter 的回复:]
引用 2 楼 dazzlingwinter 的回复:
Java codepublicsynchronizedvoid dothis(){try {
        Thread.sleep(4000);
        System.out.println(this.messages);
        this.messages.clear();
    }catch (InterruptedException e) {
        e.printStackTrace();
    }
}
改一下,看这样行不?

没有具体跑你的代码
[/Quote]

其他方法貌似可行的,只是工作需求只想把messages对象锁住。 ,但是就是搞不懂为什么锁不住对象。
nihuajie05 2010-01-07
  • 打赏
  • 举报
回复
ls犯2了,大家躲让
Kanepan 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 nihuajie05 的回复:]
B执行完了dothis,不就解锁了么?
然后C就执行2步add啊
我不明白楼主纠结所在?
run里面只是线程要执行的序列,不代表该进程要一直跑,跑完了重新跑,再跑。。。

是不是这么一说来着,楼下继续
[/Quote]

C 执行add的时候,message对象已经被锁住了,按理说应该被锁住的,为什么还能继续操作?
Dazzlingwinter 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 dazzlingwinter 的回复:]
Java codepublicsynchronizedvoid dothis(){try {
Thread.sleep(4000);
System.out.println(this.messages);
this.messages.clear();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
改一下,看这样行不?
[/Quote]
没有具体跑你的代码

62,621

社区成员

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

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