简体   繁体   English

同步方法与ReentrantLock

[英]Synchronized Method vs ReentrantLock

Say I have a server with multiple threads that share a reference to a Data instance. 假设我有一台具有多个线程的服务器,这些线程共享对Data实例的引用。 Quick eg, 快速例如

edit1: Updated for readability edit1:已更新以提高可读性

public void main() {
 Data data = new Data();
 ReentrantLock rl = new ReentrantLock(true);
 ReadThread t1 = new ReadThread(data, rl);
 UploadThread t2 = new UploadThread(data, rl);
 t1.start(); t2.start();
}

class ReadThread extends Thread {
private Data data;
private ReentrantLock lock;

ReadThread(Data d, ReentrantLock l){ data = d; lock = l; }

     void run(){
        lock.lock();
        try{
        data.put(aString)
        } finally { lock.unlock(); }
     }
}

class UploadThread extends Thread {
private Data data;
private ReentrantLock lock;

UploadThread(Data d, ReentrantLock l){ data = d; lock = l; }

     void run(){
        lock.lock();
        try{
        data.put(aString)
        } finally { lock.unlock(); }
     }
}

Is it better to use locks like above, or synchronize the put method like below, 像上面那样使用锁,还是像下面那样同步put方法,

class Data {
 private LinkedList<String> data = new LinkedList<String>();
 synchronized void put(String x){ data.add(x); }
}

This is pretty rough, 这很粗糙

I'm mostly just concerned about the concurrency. 我主要只是担心并发性。

With the synchronized method am I correct in assuming the synchronization would occur on the class' "Data" instance/object? 使用同步方法,假设同步将发生在类的“数据”实例/对象上,我是否正确? So one UploadThread could call the put procedure/method and one ReadThread could do the same in parallel. 因此,一个UploadThread可以调用put过程/方法,而一个ReadThread可以并行执行相同的操作。 However using the ReentrantLock example, only one thread would be able to execute a put call at any one time? 但是,使用ReentrantLock示例,在任何时候只有一个线程能够执行put调用吗?

What would happen if in the "Data" class I made the LinkedList static and I made the put method synchronized and static? 如果在“ Data”类中将LinkedList设为静态,并将put方法设为同步和静态,会发生什么情况? Which is the best approach? 哪种方法最好? Do I lose mut ex if I make things static? 如果我使事物静态化,我会失去mut ex吗?

In Java synchronized sections are reentrant. 在Java中, synchronized节是可重入的。 This means that a single thread can enter the synchronized section as many times as required, but a new thread can only enter when no other threads are present. 这意味着单个线程可以根据需要多次进入同步部分,但是只有在不存在其他线程时才可以进入新线程。 A thread currently within these sections has acquired a lock and will only return the lock upon leaving all synchronized sections. 这些部分中当前存在的线程已获得锁定,并且仅在离开所有同步部分后才返回该锁定。 Apart from declaring synchronized through the method signature, synchronized can also be called on objects directly. 除了声明synchronized通过方法签名, synchronized也可以在对象直接调用。 For example; 例如; these two methods will have the same effect: 这两种方法将具有相同的效果:

synchronized public void foo() {

}

public void foo() {
    synchronized(this) {

    }
}

The ReentrantLock is very similar to synchronized in that only one thread can acquire the lock at one time. ReentrantLocksynchronized非常相似,因为只有一个线程一次可以获取锁。 If a thread reaches a lock.lock() statement it will wait until the lock is unlocked by another thread. 如果一个线程到达lock.lock()语句,它将等待直到另一个线程将锁解锁。 If the thread already has the lock it will continue. 如果线程已经具有锁,它将继续。 This can be useful in more complicated situations where a single synchronized code block isn't enough. 这在单个同步代码块还不够的更复杂情况下很有用。

What would happen if ... I made the put method synchronized and static? 如果...使同步同步和静态放置方法会怎样?

If the method is static synchronized that means you are locking the class itself and not the instance of the class. 如果该方法是static synchronized ,则意味着您锁定的是类本身而不是类的实例。 It is locked independently of an instance synchronized method. 它独立于实例synchronized方法被锁定。


For your code: 对于您的代码:

The easiest thing to do here would be to make the Data object into a thread safe object. 这里最简单的事情是将Data对象变成线程安全对象。 If you are not able to edit the code for this class, then one valid strategy would be to wrap the object in a thread safe wrapper. 如果您无法编辑此类的代码,则一种有效的策略是将对象包装在线程安全包装器中。

interface Foo {
    void bar();
} 
class UnsafeFoo implements Foo {
    @Override bar() { ... }
}
class ThreadSafeFoo implements Foo {
    Foo foo;
    ThreadSafeFoo(Foo foo) { this.foo = foo; } 
    @Override synchronized bar() { foo.bar(); }
}

Foo unsafe = new UnsafeFoo();
Foo safe = new ThreadSafeFoo(unsafe);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM