比如说:
String tt[] = new String[100];
synchrnized(tt)
{
.....
}
即当多线程访问tt数组时要同步。但是有一个问题,现在这种情况是线程1和线程2同时访问tt,即使两个线程不是访问同一个地址,比如:线程1访问tt[0],线程2访问tt[1],线程间也要加锁,这大大影响效率。有没有什么办法让多线访问一个地址时才加锁?即线程1访问tt[0],线程2访问tt[1],线程间不加锁;只有线程1访问tt[0],线程2也访问tt[0],线程间才加锁?
我试过
synchrnized(tt[i])
{
.....
}
但是不行,系统还是默认块是tt,而不是tt的某个指针对象。苦恼了很久,现在手底下的项目等着用这种技术,望高手指点,不胜感激。

解决方案 »

  1.   

    你的tt是哪里定义的,比如下面这个局部变量就等于没锁。
    void foo() {
      String[] tt new String[]....;
      syncrhonized(tt) { // 或者tt[i]
      }
    }即使是全局的,tt[i] 也可以随时变更,比如线程1锁定的时候tt[0]="abc",到线程2就变成了"xyz",自然锁不住。而且,即使都是"abc",它们也并不一定是同一个对象。所以锁定字符串的时候一般使用"...".intern()。回到你的问题,你的目的是同步tt数组。你可以
    private final Object lock = new Object();public void foo() {
      synchronized(lock) {
        // tt operation
      }
    }// 这个也可以
    public synchronized void foo2() {
      // tt operation
    }
      

  2.   


    private final Object lock = new Object();public void foo() {
      synchronized(lock) {
        // tt operation
      }
    }学习
      

  3.   

    你这种想法很好啊,可能你还不知道,这是一种进行同步的一种方式,名叫分离锁(striping lock)。分离锁是通过不同的锁锁住共享对象的一部分。是一种非常高效的同步方式。不过你不能使用当前操作对象去锁,你试试看这样能行不?class GuardString {    private String[] str;
        private Object[] locks;    private final static int DEFAULT_LOCK_COUNT = 16;    public GuardString(int len) {
            this.str = new String[len];
            this.locks = new Object[DEFAULT_LOCK_COUNT];
        }    public void setValue(int index, String s) {
            checkIndex(index);
            synchronized (lockObject(index)) {
                str[index] = s;
            }
        }    public String removeValue(int index) {
            checkIndex(index);
            synchronized (lockObject(index)) {
                return str[index];
            }
        }    private void checkIndex(int index) {
            if(index < 0) {
                throw new IllegalArgumentException("index must be greater than or equals 0");
            }
            if(index > str.length - 1) {
                throw new IllegalArgumentException("index must be less than " + (str.length - 1));
            }
        }    private Object lockObject(int index) {
            return locks[index % DEFAULT_LOCK_COUNT];
        }
    }
      

  4.   

    JDK 5 中有个类叫 java.util.concurrent.ConcurrentHashMap 这是个非常高效、线程安全的 HashMap 实现。其内部就是采用分离锁来实现的。通过 key 的 hashCode 找到对应的锁,仅锁住一小块区域。ConcurrentHashMap 默认采用了 16 把分离锁,也就意味着最多允许 16 个线程并发地对这个容器进行操作。
      

  5.   


    呵呵,我初始化了哦 :-)    public GuardString(int len) {
            this.str = new String[len];
            this.locks = new Object[DEFAULT_LOCK_COUNT];
        }
      

  6.   

    哦,对哦,对象数组初始化好后元素是 null,呵呵。不好意思  竟然犯了那么低级的错误 
      

  7.   

    原来如此~synchronized()中的要锁的块其实是相当于信号量的概念~我明白了,我现在试试火龙的方法,结果我一会发上来
      

  8.   

    我试了~~按你的做法,无法达到分离锁的目的,因为synchronized(Object[i])无法识别对象指针,而是把Object[i]看做1个整体的对象Object。不论是Object[1]还是Object[5],synchronized()都同意把他们看成Object,因此加的锁就是1个,不知道还有什么别的好办法。
      

  9.   

    不好意思,是我的错,我把Object[i]的内容初始化成一样的了,所以都指向一个对象。把他们的对象变为不一样,分离锁就实现了,火龙果的方法很好,谢谢各位了。如还有问题欢迎提问。
      

  10.   

    我在 4 楼的那段代码写得有问题,锁对象没有初始化,不能直接用,订正之后:    public GuardString(int len) {
            this.str = new String[len];
            initLocks();
        }    private void initLocks() {
            locks = new Object[DEFAULT_LOCK_COUNT];
            for(int i = 0; i < locks.length; i++) {
                locks[i] = new Object();
            }
        }
      

  11.   

    另外,不建议 String[] 有多少个数据就设多少把锁,这样做没有什么必要,毕竟达不到这么高的并发量。设成固定锁的数量,采用数值索引值去 mod 一下计算需要哪把锁就行了。如果需要增加锁的数量,更改一下初始化的值就可以了。