我在我的类Server中有一个Data实例,在2个线程之间共享:
public class Server{
public static void main(String[] args){
Data data = new Data();
Thread t1=new Thread(new ClientService(data));
Thread t2=new Thread(new PromoService(data));
t1.start();
t2.start();
}
以下是我班级的相关部分:
public class ClientService implements Runnable{
public Data data;
public ClientService(Data data){
this.data = data;
}
public void run(){
this.data.newClient(t[1],Integer.parseInt(t[2]),Integer.parseInt(pass),ia);
}
这里,假设t是一个String数组,我是一个InetAdress并传递一个字符串(我删除了创建这些变量的代码部分,使其更简单)。
public class Data implements Serializable{
public ArrayList<ClientData> listClient;
public Data(){
this.listClient = new ArrayList<ClientData>();
}
public synchronized boolean newClient(String id,int port,int pass,InetAddress ia){
for(int i = 0 ; i < listClient.size(); i ++){
if(listClient.get(i).id.equals(id) ){
return false;
}
}
ClientData ncl = new ClientData(port,ia,id,pass);
this.listClient.add(ncl);
return true;
}
在newClient()之前,listClient不包含任何内容(size = 0)。在调用之后我尝试打印listClient并且大小变为1,但是包含的元素为null。我不明白:阻碍将新的ClientData对象添加到此共享变量的东西是什么? 当我尝试时,我确保此线程是唯一一个在此时访问或修改实例的线程。
答案 0 :(得分:0)
根据我的评论,当您从A
读取时需要同步,因为它会强制线程之间的内存一致性。在没有同步的情况下,某些线程x
可以对某个变量B
进行更改,而另一个线程x
不需要将更改视为synchronized (data) { /* look at what's in data.listClient */ }
。同步强制线程查看对共享内存的更改。
从技术上讲,这是因为CPU有一个本地缓存,它临时存储变量。同步强制CPU从主内存加载变量,而不是查看可能过时的缓存。
因此,listClient
强制读者线程看到在同步方法newClient
期间对synchronized (this)
所做的任何更改。 (同步实例方法与size
相同。)
从你的描述中,听起来读者线程看到列表的{{1}}增加但从未看到对支持数组的更改。