Java 同步块——锁定对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18156954/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:52:16  来源:igfitidea点击:

Java synchronized blocks -- lock objects

javasynchronized

提问by Roam

In the sample code

在示例代码中

public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();

public void inc1() {
    synchronized(lock1) {
        c1++;
    }
}

public void inc2() {
    synchronized(lock2) {
        c2++;
    }
}
}

on thispage,

这个页面上,

lock1and lock2are controlling the updates on c1and c2resply.

lock1lock2正在控制c1c2回复上的更新。

However,

然而,

    synchronized(lock2) 

is acquiring the lock of the object lock1and releasing it when the synchronized block

正在获取对象lock1的锁并在同步块时释放它

    synchronized(lock1) {
        c1++;
    }

is executed.

被执行。

While this block is being executed, there may be an update on member c1of thisobject still-- and I don't see how this update is being prevented by synchronizing on lock1as in the code.

当正在执行该块,有可能是在构件的更新C1目的和still--我看不出是由上同步防止此更新锁1中的代码。

It is the object lock1that there is exclusive access on-- and nothing else(?)

对象lock1有独占访问权限——除此之外别无他物(?)

So, how is the implementation

那么,执行情况如何

public void inc1() {
    synchronized(lock1) {
        c1++;
    }
}

in the above code different from

在上面的代码中不同于

public void synchronized inc1() {
        c1++;
}

or even

甚至

public void inc1() {
    synchronized(c1) {
        //do something on c1
    }
}

when c1is an object but not a primitive?

c1是一个对象而不是一个原始类型时?

What am I missing here ?

我在这里错过了什么?

Note: I saw

注:我看到了

What is the difference between synchronized on lockObject and using this as the lock?

在 lockObject 上同步和使用 this 作为锁有什么区别?

and

Java synchronized method lock on object, or method?

Java同步方法锁定对象或方法?

among some other discussions.

在其他一些讨论中。

采纳答案by rgettman

Implementation 1.

实施 1.

You are locking on the lock1object. Nothing else that needs a lock on lock1can execute. Having your two methods lock on different objects means that the two methods can run concurrently, but no two threads can run the same method concurrently.

您正在锁定lock1对象。没有其他需要锁定的东西lock1可以执行。将两个方法锁定在不同的对象上意味着这两个方法可以并发运行,但没有两个线程可以同时运行相同的方法。

Implementation 2.

实施 2.

Making a method synchronizedmeans that the entire method body is implicitly in a synchronized(this)block (or synchronized on the Classobject if the method is static. If both methods are synchronized, then one method would prevent the other from running at the same time, which is different then locking both methods on different objects.

创建一个方法synchronized意味着整个方法体隐式在一个synchronized(this)块中(如果方法是,则在Class对象上同步static。如果两个方法都是synchronized,那么一个方法会阻止另一个同时运行,这与锁定两者不同不同对象的方法。

Implementation 3.

实施 3.

If c1is an object and not a primitive, then the semantics are very similar to implementation 1 - locking on an explicit object.

如果c1是对象而不是原语,则语义与实现 1 非常相似 - 锁定显式对象。

回答by Martijn Courteaux

Your statement is as far as I know incorrect. The page you linked doesn't state what you claim in your question neither. This is how locks work: Locks do notprevent threads of accessing an object at all. Locks only prevents another thread of acquiring the same lockwhile another thread already has acquired that lock.

据我所知,你的说法是错误的。您链接的页面也没有说明您在问题中声称的内容。这就是锁的工作原理:锁根本不会阻止线程访问对象。锁只会阻止另一个线程获取相同的锁,而另一个线程已经获取了该锁。

This means that this can happen:

这意味着这可能发生:

Thread A: synchronize (lockObject)
Thread B: lockObject.toString();
Thread A: release the lock on lockObject

This is what happens when two Threads want the same lock at the same time:

当两个线程同时想要同一个锁时会发生这种情况:

Thread A: synchronize (lockObject)
Thread B: synchronize (lockObject) // This will block until (1) !
Thread A: do some stuff and then release lock on lockObject
Thread B: gets the lock (1)

However:

然而:

public void synchronized inc1() {
    c1++;
}

is exactly the same as:

完全相同:

public void inc1() {
    synchronized(this) {
        c1++;
    }
}

回答by chrylis -cautiouslyoptimistic-

Marking a block or method synchronizedwithout specifying a lock object synchronizes on the object who owns the method; in this case, the MsLunchinstance. It's equivalent to synchronized(this). The purpose of the lock-object idiom is to break that lock up so that c1and c2can be manipulated separately. A synchronizedblock can only synchronize on an object, not a primitive.

synchronized不指定锁对象的情况下标记块或方法会在拥有该方法的对象上同步;在这种情况下,MsLunch实例。它相当于synchronized(this). 锁定对象习语的目的是打破锁定,以便c1c2可以单独操作。一个synchronized块只能在一个对象上同步,而不是一个基元。

回答by bolei

synchronized(lock2){
  // do sth
}

is actually acquiring lock of object lock2

实际上是获取对象lock2的锁

where as

然而

public void synchronized inc1() {
        c1++;
}

acquires object on this object.

获取此对象上的对象。

locks acquired by synchronized will be released once the program leaves the block.

一旦程序离开块,synchronized 获取的锁将被释放。

回答by sadjkas sadal

I was having trouble with one thread hogging the lock

我在一个线程占用锁时遇到了麻烦

for(;;){synchronized(lockObject){
...
}}

I guess Java doesn't like to unlock it on its own the first chance it gets.

我猜 Java 不喜欢第一次有机会就自己解锁它。

Using an java.util.concurrent.locks.ReentrantLock fixed the problem

使用 java.util.concurrent.locks.ReentrantLock 解决了这个问题

static ReentrantLock lock = new ReentrantLock();
for(;;){
  lock.lock();
  ...
  lock.unlock();
}