首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java同步:同步方法和同步块

Java同步:同步方法和同步块
EN

Stack Overflow用户
提问于 2012-07-09 14:40:41
回答 2查看 992关注 0票数 1

我有一个mulitThread Java应用程序。在一种方法中,需要同步ArrayList。因为arrayList不是线程安全的,所以我必须使用同步。问题是ArrayList类型的对象不是该对象的成员变量。该方法的原型如下:

代码语言:javascript
复制
public void simultaneousAccess(ArrayListWrapper aListWrapper){
  ArrayList list = aListWrapper.getList();
  //...Codes manipulate the list            
}

由于是多线程,我应该使用

a)

代码语言:javascript
复制
 public void synchronized simultaneousAccess(ArrayListWrapper aListWrapper){
         ArrayList list = aListWrapper.getList();
         //...Codes manipulate the list            
    }

b)

代码语言:javascript
复制
public void simultaneousAccess(ArrayListWrapper aListWrapper){
     ArrayList list = aListWrapper.getList();
     Synchronized(list){
         //...Codes manipulate the list 
     }           
 }

从性能测试来看,这两种方法都不起作用。但我不知道为什么?

下面是完整的源代码:

代码语言:javascript
复制
package com.juhani.prototype.sync;

import java.util.ArrayList;

public class ArrayListWrapper {
    public ArrayList<Integer> aList = new ArrayList<Integer>();

    public ArrayListWrapper(){
        Integer one = new Integer(1);
        Integer two = new Integer(2);
        Integer three = new Integer(3);

        aList.add(one);
        aList.add(two);
        aList.add(three);
    }
}

package com.juhani.prototype.sync;

import java.util.ArrayList;

public class TestClass {

    public int count_test=0;

    public synchronized void test(ArrayListWrapper listWrapper){        
        ArrayList<Integer> list = listWrapper.aList;  
        int temp = list.get(1)+1;
        list.set(1,temp);       
    }

    public void testBlock(ArrayListWrapper listWrapper){
        ArrayList<Integer> list = listWrapper.aList;  
        synchronized(list){
            int temp = list.get(1)+1;
            list.set(1,temp);     
        }
    }

}


package com.juhani.prototype.sync;

public class WorkerSyncObj extends Thread {

    ArrayListWrapper listWrapper = null;
    TestClass tc = null;
    int number;

    public WorkerSyncObj(int aNumber){
       number = aNumber;    
    }

    public void setListWrapper(ArrayListWrapper aListWrapper){
        listWrapper = aListWrapper;
    }

    public void setTestClass(TestClass aTc){
        tc = aTc;
    }

    public void run(){
        int i = 1000;
        for(int j=0;j<i;j++){
            tc.testBlock(listWrapper);
            System.out.println("Thread "+number+" is runing at loop "+j+" . index 1 value is:"+listWrapper.aList.get(1)); 
        }       
    }   
}

package com.juhani.prototype.sync.main;

import com.juhani.prototype.sync.ArrayListWrapper;
import com.juhani.prototype.sync.TestClass;
import com.juhani.prototype.sync.WorkerSyncObj;

public class TestMain {

    public static void main(String[] args){

        ArrayListWrapper list = new ArrayListWrapper();
        TestClass tc = new TestClass();

        WorkerSyncObj work1 = new WorkerSyncObj(1);
        work1.setListWrapper(list);
        work1.setTestClass(tc);
        WorkerSyncObj work2 = new WorkerSyncObj(2);
        work2.setListWrapper(list);
        work2.setTestClass(tc);
        WorkerSyncObj work3 = new WorkerSyncObj(3);
        work3.setListWrapper(list);
        work3.setTestClass(tc);

        work1.start();
        work2.start();
        work3.start();



    }

}
EN

回答 2

Stack Overflow用户

发布于 2012-07-09 14:53:39

在第一种情况下,锁定this对象,而在第二种情况下,锁定list对象。如果从不同的对象调用该方法,但列表是相同的,这可能是一个问题。这可能是第一种情况下出现异常的原因。

或者,您可以尝试一些内置的并发类型,如Collections.synchronizedListCopyOnWriteArrayList

票数 5
EN

Stack Overflow用户

发布于 2012-07-12 13:54:44

在java中,每个对象实例都有一个内部锁(以及相应的类本身)。同步的密钥工作实际上是使用内部锁来进行独占访问,即

代码语言:javascript
复制
syncrhonized method(...) {...} 

等于

代码语言:javascript
复制
method(...) { 
this.intrinsicLock.lock(); 
...; 
this.intrinsicLock.unlock() }

代码语言:javascript
复制
synchronized( obj_ref ) { ... }

等于

代码语言:javascript
复制
obj_ref.intrinsicLock.lock(); 
{...} 
obj_ref.instrinsicLock.unlock();

因此,同步化的方法对于list (参数)的保护是不正确的。如果你使用synchronized( list )有两个问题: 1.独占访问的粒度似乎有点粗略2.在整个程序中的任何地方的每个list访问都需要使用synchronized(List)。这是一个协议(用于独占访问)。

这就是为什么Java库提供了相当多的并发数据结构。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11390139

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档