簡體   English   中英

此方法是否可以在線程安全且沒有死鎖的情況下工作

[英]Will this method work thread-safe and without Deadlocks

public int saveUserToMap(User user) {
    ReentrantLock lock;
    if(this.userLocks.containsKey(user.getId())) {
        lock = this.userLocks.get(user.getId());
    } else {
        lock = new ReentrantLock();
        ReentrantLock check = this.userLocks.putIfAbsent(user.getId(), lock);
        if(check != null)
            lock = check;
    }

    if(lock.isLocked())
        try {
            lock.wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    lock.lock();

    this.users.put(user.getId(), user);
    this.usersByName.put(user.getUsername(), user);
    this.usersByEmail.put(user.getEmail(), user);

    lock.unlock();
    lock.notify();

    return user.getId();
}

嘿,我只想請Java開發人員檢查我的代碼是否是線程安全的,並且沒有死鎖,因為我想在項目中使用它。 Users,UsersByName和UsersByEmail是ConcurrentHashMap,其中String,Integer作為鍵,User對象作為Value。 UserLocks是一個帶有Integer(顯然是用戶ID作為鍵)和ReentrantLock作為值的ConcurrentHashMap。 我想同步三個HashMap。 如果有人有更好的解決方案來制作帶有三個鍵的並發地圖,最好在此處發布。 性能也很重要。

這是線程安全的。

如果userId已經在映射中,則代碼獲取鎖並使用它進行同步。 如果沒有, ConcurrentHashMap提供同步功能,以避免爭用條件為同一id使用不同的鎖。

之后,有一段無用的代碼片段,您可以擺脫掉:

if(lock.isLocked())
    try {
        lock.wait();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

不需要,因為同步是使用lock.lock() 不需要嘗試使用wait()notify()與鎖對象再次進行同步。(實際上,它沒有按預期工作,幾個線程可以在同一個鎖對象上調用lock.isLocked()並得到false直到任何一個線程調用lock.lock() ,但鎖定和解鎖之間的所有操作一次只能由單個線程執行)。

另外,通常的良好做法是在finally塊中調用lock.unlock()

我會使用synchronized做一個簡單的方法。

class UserMaps {
    private Map<Integer, User> users = new ConcurrentHashMap<>();
    private Map<String, User> usersByName = new ConcurrentHashMap<>();
    private Map<String, User> usersByEmail = new ConcurrentHashMap<>();

    public synchronized int put(User user) {
        users.put(user.getId(), user);
        usersByName.put(user.getUsername(), user);
        usersByEmail.put(user.getEmail(), user);
        return user.getId();
    }
}

只要您的所有getter也都synchronized ,這將確保所有地圖都一致更新。

但是,如果您想要更好的性能,並且希望避免所有方法都synchronized ,請使用ReadWriteLock

class UserMaps {
    ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    private Map<Integer, User> users = new ConcurrentHashMap<>();
    private Map<String, User> usersByName = new ConcurrentHashMap<>();
    private Map<String, User> usersByEmail = new ConcurrentHashMap<>();

    public int saveUserToMap(User user) {
        lock.writeLock().lock();
        try {
            users.put(user.getId(), user);
            usersByName.put(user.getUsername(), user);
            usersByEmail.put(user.getEmail(), user);
            return user.getId();
        } finally {
            lock.writeLock().unlock();
        }
    }

    public User getById(int id) {
        lock.readLock().lock();
        try {
            return users.get(id);
        } finally {
            lock.readLock().unlock();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM