Java与静态Map中的条目同步

时间:2011-10-10 16:59:17

标签: java static synchronization

我有一个静态Map,我需要同步访问。地图由用户ID键控。我想优化同步,以便我不会阻止所有线程,我只能阻止与相同用户ID相关的线程。

private static Object s_lock = new Object();
private static Map<String,User> s_users = new HashMap();
...
private someMethod() {
    synchronized(s_lock)
    {
        // keeping the global lock for as little as possible
        user=getMapEntry();
    }
    synchronized(user)   <-------- (1)
    {
        // time consuming operation
        // hopefully only blocking threads that relate to same user id.
    }
}
...
private User getMapEntry(String userId)
{
    if (s_users.containsKey(userId)) {
        user = s_users.get(userId);
    }
    else {
        user = new User();
        user.id = userId;
        s_users.put(userId, user);
    }
    return user;
}

我的问题是 - 在(1)我假设我没有持有'全局'同步锁,但由于s_users地图是静态的,这些条目是否有效静态,这意味着我仍然持有全局锁(即在类对象上同步?)

3 个答案:

答案 0 :(得分:1)

不,你很好:每个地图条目都是一个单独的对象,因此在地图条目上的同步不会在地图上同步,也不会在拥有地图的类上同步。

(顺便说一下,你的#getMapEntry(...)方法实际上返回一个,而不是一个条目。一个map条目包含对一个键的引用和一个值。)

答案 1 :(得分:0)

这应该有用;第二个块仅在此用户上同步。

小测试:

public class Test {

    protected class User {
        String id;
    }
    private static Object s_lock = new Object();
    private static Map<String,User> s_users = new HashMap<String, User>();

    public void someMethod(String id) throws InterruptedException {
        User user;
        synchronized(s_lock)
        {
            // keeping the global lock for as little as possible
            user = getMapEntry(id);
        }
        synchronized(user)
        {
            System.out.println("Waiting for user: "+user.id);
            Thread.sleep(10000);
        System.out.println("Finished waiting for user: "+user.id);
        }
    }

    private User getMapEntry(String userId)
    {
        User user;

        if (s_users.containsKey(userId)) {
            user = s_users.get(userId);
        }
        else {
            user = new User();
            user.id = userId;
            s_users.put(userId, user);
        }

        return user;
    }

    public static void main(String[] args) throws InterruptedException {
        final Test test = new Test();

        for(int i = 0; i < 10; i++) {
            final int j = i;

            new Thread() {
                public void run() {
                    try {
                        test.someMethod(String.valueOf(j % 5));
                    } catch (InterruptedException e) {}
                }
            }.start();
        }
    }
}

输出:

Waiting for user: 0
Waiting for user: 1
Waiting for user: 3
Waiting for user: 2
Waiting for user: 4
Finished waiting for user: 0
Finished waiting for user: 1
Waiting for user: 1
Waiting for user: 0
Finished waiting for user: 3
Finished waiting for user: 2
Waiting for user: 3
Waiting for user: 2
Finished waiting for user: 4
Waiting for user: 4
Finished waiting for user: 0
Finished waiting for user: 1
Finished waiting for user: 3
Finished waiting for user: 2
Finished waiting for user: 4

所以没关系。

答案 2 :(得分:0)

你没有在类对象上同步,但我正在做你认为它正在做的事情:

  • 不同的主题使用共享的s_lock访问地图。但我认为您也可以{/ 1}} s_usersfinal

  • 访问相同synchronize对象的不同线程执行“耗时的操作” “按顺序。

我看到的唯一注意事项是对象是否在地图中保持同一User的变化。只要一个User只有一个User对象,你就可以了。

我做了类似的事情但在userId上同步了。它有它的缺点,但对我的情况很好。