使用密钥来同步对代码块的访问 [英] Use of a key to synchronize access to code block

查看:34
本文介绍了使用密钥来同步对代码块的访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常,我会锁定如下所示的关键部分.

Normally I would lock on a critical section like the following.

public class Cache {
    private Object lockObject = new Object();

    public Object getFromCache(String key) {
        synchronized(lockObject) {

            if (cache.containsKey(key)) {
                // key found in cache - return cache value
            }
            else {
                // retrieve cache value from source, cache it and return
            }
        }
    }
}

我的想法是避免出现竞争状况,竞争状况可能导致数据源被多次击中并且密钥被多次添加到缓存中.

The idea being I avoid a race condition which could result in the data source being hit multiple times and the key being added to the cache multiple times.

现在,如果两个线程同时进入用于不同缓存键,我仍将阻止一个线程.

Right now if two threads come in at about the same time for different cache keys, I will still block one.

假设键是唯一的-锁仍可以通过锁定键来工作吗?

Assuming the keys are unique - will the lock still work by locking on the key?

我认为无效,因为我知道对象引用应该相同,锁才能生效.我想这取决于它如何检查是否相等.

I think it won't work because I understand that the object reference should be the same for the lock to come into effect. I guess this comes down to how it checks for equality.

public class Cache {

    public Object getFromCache(String key) {
        synchronized(key) {

            if (cache.containsKey(key)) {
                // key found in cache - return cache value
            }
            else {
                // retrieve cache value from source, cache it and return
            }
        }
    }
}

推荐答案

每个对象都有一个隐式监视器,可以在该监视器上进行同步.字符串对象可以在堆中创建,并且对于同一组字符(如果使用 new 创建)也可以不同,或者可以来自池中.只有两个线程在同一对象上同步时,它们才会访问具有同步块的关键部分.

Each object has an implicit monitor upon which synchronization works. String object may be created in heap and also may be different for same set of characters (if created by using new) or may be from pool. Two threads will acess the critical section with synchronized block only if they synchronize on same object.

在String文字上同步确实是一个坏主意.池中的字符串文字是共享的.试想一下,如果在代码的两个不同部分,您有两个同步的部分,并且您在String的两个引用上进行了同步,但已使用具有相同字符集的字符串进行了初始化,如果使用了池中的String,则两个位置都将是同一对象.即使这两个地方可能具有不同的业务环境,但仍然可能最终导致应用程序被挂起.调试也将非常困难.

Synchronizing on String literal is really a bad idea. String literal from pool are shared. Just imagine if at two different parts of your code you are having two synchronized sections and you synchronize on two references of String but initilized with string with same set of characters, if String from pool is used then both the places it will be the same object. Even though both the places may have different business context but still you may end up in your application being hanged. It will be very difficult to debug too.

对于特定于的问题,如果对密钥进行同步,则将解决该目的.

For the specific to the question of will the purpose be solved if synchronization is done on keys.

您要避免两个线程尝试在不读取高速缓存的最新值的情况下进行写操作.您将为每个条目使用不同的密钥.假设线程1和线程2要访问相同的键,然后在同一键对象上进行同步将阻止它们都进入同步块.同时,如果线程3要访问另一个不同的密钥,那么它可以很好地做到这一点.在这里,我们看到与所有键的读写相比,单个对象的读写速度更快.到目前为止,还算不错,但是如果假设您要保留一个数组或任何其他类似的非线程安全数据结构来存储缓存的值,就​​会出现问题.同时写入(针对两个或多个不同的键)可能导致一个写入被同一索引处的另一个写入覆盖.

You want to avoid two threads trying to write without reading the latest value of cache. You will have different key for each entry. Suppose a thread1 and thread2 wants to access the same key then synchronization on the same key object will prevent both of them to enter the synchronized block. Meanwhile if a thread3 wants to access another different key then it can very well do so. Here we see the read and writes are faster as compared to single common object for reads and writes for all keys. So far so good but the problem will arise if suppose you are keeping an array or any other similar non thread safe data structure for storing the cached values. Simultaneous writes (for two or more different keys) can result in one write being overwritten by another at same index.

因此,取决于缓存数据结构的实现方式,如何为多线程环境中的更快读写做好最好的准备.

So it depends upon the implementation of cache data structure how best you can prepare it for faster read and writes in a multi threaded enviornment.

这篇关于使用密钥来同步对代码块的访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆