Java 锁定具有某些分区属性的对象

问题描述 投票:0回答:2

我有一个具有某些属性的类(下例中的分区)

class Car {
   public String partition;
   ....
}

我有一个功能

private void doSomething(Car car){
   //  
     Object obj = getLock(car); // should write this function
     synchronized (obj){
          // do work here
     }

}

如果我有 Car 对象的 2 个实例

从 2 个不同的线程调用函数 doSomething。同步块应该只同步具有相同“分区”值的对象。当 2 个汽车对象具有不同的分区键时,它们可以同时进入代码块

我想知道如何编写“getLock”函数。我应该使用一些地图吗

Map<String,Object> ? 

是否有更好的方法来防止具有相同属性的 2 个对象进入临界区?

java multithreading locking
2个回答
1
投票

是的,使用 Map 是实现 getLock 函数的合适方法,以便根据 Car 对象的分区属性实现同步。该映射可用于存储每个唯一分区值的锁对象。

示例实现:

import java.util.HashMap;
import java.util.Map;

class Car {
    public String partition;
    // ...
}

public class CarManager {
    private Map<String, Object> lockMap = new HashMap<>();

    private Object getLock(Car car) {
        String partition = car.partition;
        synchronized (lockMap) {
            // Check if a lock object exists for the partition
            if (!lockMap.containsKey(partition)) {
                // If not, create a new lock object and store it in the map
                lockMap.put(partition, new Object());
            }

            // Return the lock object for the partition
            return lockMap.get(partition);
        }
    }

    private void doSomething(Car car) {
        Object obj = getLock(car);
        synchronized (obj) {
            // do work here
        }
    }
}

0
投票

如果你确实想使用锁定,我会看一下条纹锁。一些伪代码:

class CarManager{
    final Object[] lockStripe = new Object[Runtime.availableProcessors()*4];

     public CarManager(){
        for(int k=0;k<lockStripe.length;k++){
           lockStripe[k]=new Object();
        }
     }

     Object getLock(Car car){
         int hash = car.partition.hashCode();
         int lockIndex;
    
           if (hash == Integer.MIN_VALUE) {
              lockIndex = 0;
           } else {
               lockIndex = abs(hash) % lockStripe.length;
           }
      
           return lockStripe[lockIndex];
     }

     public void doSomething(Car car){
         synchronized(getLock(car)){
            ...
         }
     }

这种方法将确保:

  1. 同一分区中的汽车最终将拥有相同的锁。
  2. 不同分区中的汽车以相同的锁结束的概率很低。您可以通过更改 lockStripe 的长度在内存利用率和争用之间做出权衡。
  3. 没有获取全局锁
  4. 不锁你不拥有的物品。
  5. 不会因为保留不再存在的对象的锁而导致内存泄漏。
  6. 没有数据竞争
© www.soinside.com 2019 - 2024. All rights reserved.