Java多线程-无等待锁定
我有一个java多线程问题。我有两个线程访问methodA(),该methodA()内部有for循环,循环中调用methodB()。方法A应该使用线程名称锁锁定,方法B应该在方法B操作的对象id上锁定。检查下面的代码 当前代码Java多线程-无等待锁定,java,multithreading,locking,wait,Java,Multithreading,Locking,Wait,我有一个java多线程问题。我有两个线程访问methodA(),该methodA()内部有for循环,循环中调用methodB()。方法A应该使用线程名称锁锁定,方法B应该在方法B操作的对象id上锁定。检查下面的代码 当前代码 private static final ConcurrentHashMap<Object, Object> LOCKS = new ConcurrentHashMap<Object, Object>(); p
private static final ConcurrentHashMap<Object, Object> LOCKS = new ConcurrentHashMap<Object, Object>();
private void methodA(){
LOCKS.putIfAbsent(Thread.currentThread().getName(), new Object()))
synchronized (LOCKS.putIfAbsent(Thread.currentThread().getName(), new Object())) {
for(loop through all objects) {
methodB(Object1);
}
}
}
private void methodB(Object1 object1) {
LOCKS.putIfAbsent(object1.getObjectId(), new Object()))
synchronized(LOCKS.putIfAbsent(object1.getObjectId(), new Object())){
//<Work on object1>
}
}
私有静态最终ConcurrentHashMap锁=新ConcurrentHashMap();
私有无效方法a(){
LOCKS.putIfAbsent(Thread.currentThread().getName(),new Object())
已同步(LOCKS.putIfAbsent(Thread.currentThread().getName(),new Object()){
for(通过所有对象循环){
方法b(对象1);
}
}
}
私有无效方法B(Object1 Object1){
LOCKS.putIfAbsent(object1.getObjectId(),new Object())
已同步(LOCKS.putIfAbsent(object1.getObjectId(),new Object()){
//
}
}
我编写上述代码是为了确保两个不同的线程能够并行访问methodA(),但不能在methodB()中同时处理同一个Object1(methodA()调用)。
ie;虽然我希望线程A和线程B同时访问methodA(),而methodA()又将循环遍历“for”循环中的所有对象,并通过调用methodB()对每个对象进行操作,但我不希望线程A和线程B同时作用于同一个对象实例。因此,上面的代码基于对象实例ID锁定methodB()
需要改进。
在上面的代码中,如果线程A和线程B来到methodB()并发现它们都想处理同一个对象“obj1”,那么现在使用上面的代码,线程A将等待,或者线程B将等待另一个线程完成,具体取决于谁先到达并锁定了methodB()
但是想象一下,线程a首先获得锁,然后执行methodB()需要9个小时才能完成对“obj1”的处理。在这种情况下,线程B需要等待整整9个小时才能有机会执行methodB(),从而处理“obj1”
我不想发生这种事。线程B发现methodB()被线程A以“obj1”的名称锁定后,应继续(稍后返回obj1)尝试锁定和处理其他对象。ie;它应该尝试处理“for”循环中的其他对象,如对象列表中的obj1、obj2等
任何解决“无等待锁定”问题的输入都将受到欢迎
非常感谢您的帮助
一些澄清以改进答案。
你能做的最好的事情就是保持简单 应该使用线程名称锁来锁定方法A 只有锁定共享对象才有意义。锁定线程本地锁是没有意义的 已同步(LOCKS.putIfAbsent(object1.getObjectId(),new Object()) 它将返回
null
,并在第一次运行时抛出NullPointerException
我会将代码替换为
private void methodA(){
List<Object1> objects = new ArrayList<>(this.objectList);
while(true) {
for(Iterator<Object1> iter = objects.iterator() : objects)
if(object1.methodB())
iter.remove();
if(objects.isEmpty()) break;
Thread.sleep(WAIT_TIME_BEFORE_TRYING_AGAIN);
}
}
// in class for Object1
final Lock lock = new ReentrantLock();
public boolean methodB() {
if (!lock.tryLock())
return false;
try {
// work on this
return true;
} finally {
lock.unlock();
}
}
private void methodA(){
List objects=new ArrayList(this.objectList);
while(true){
for(迭代器iter=objects.Iterator():objects)
if(object1.methodB())
iter.remove();
如果(objects.isEmpty())中断;
睡眠(在再次尝试之前等待一段时间);
}
}
//为Object1上课
最终锁定=新的可重入锁定();
公共布尔方法B(){
如果(!lock.tryLock())
返回false;
试一试{
//做这个
返回true;
}最后{
lock.unlock();
}
}
根据您想要如何处理无法锁定的对象,您可以将它们添加到后台执行器服务中。您可以让methodA重复调用失败的所有剩余对象
理想情况下,您会找到一种方法,以尽量减少锁定的时间,甚至完全消除锁定的需要。e、 像AtomicReference和CopyOnWriteArrayList这样的类是线程安全的,没有锁的。你能做的最好的事情就是保持简单 应该使用线程名称锁来锁定方法A 只有锁定共享对象才有意义。锁定线程本地锁是没有意义的 已同步(LOCKS.putIfAbsent(object1.getObjectId(),new Object()) 它将返回
null
,并在第一次运行时抛出NullPointerException
我会将代码替换为
private void methodA(){
List<Object1> objects = new ArrayList<>(this.objectList);
while(true) {
for(Iterator<Object1> iter = objects.iterator() : objects)
if(object1.methodB())
iter.remove();
if(objects.isEmpty()) break;
Thread.sleep(WAIT_TIME_BEFORE_TRYING_AGAIN);
}
}
// in class for Object1
final Lock lock = new ReentrantLock();
public boolean methodB() {
if (!lock.tryLock())
return false;
try {
// work on this
return true;
} finally {
lock.unlock();
}
}
private void methodA(){
List objects=new ArrayList(this.objectList);
while(true){
for(迭代器iter=objects.Iterator():objects)
if(object1.methodB())
iter.remove();
如果(objects.isEmpty())中断;
睡眠(在再次尝试之前等待一段时间);
}
}
//为Object1上课
最终锁定=新的可重入锁定();
公共布尔方法B(){
如果(!lock.tryLock())
返回false;
试一试{
//在…上工作