2016-11-29 63 views
0

说我有一个服务器与多个线程共享一个数据实例的引用。快速例如,同步方法vs ReentrantLock

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(); } 
    } 
} 

是更好地使用锁像上面,或同步像下面的put方法,

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

这是相当粗糙,

我大多只关心并发性。

使用同步方法我是否正确地假设在类的“Data”实例/对象上会发生同步?因此一个UploadThread可以调用put过程/方法,一个ReadThread可以并行执行相同的操作。然而,使用ReentrantLock示例,只有一个线程可以在任何时候执行put电话吗?

如果在“数据”类中,我将LinkedList设置为静态,并且使put方法同步且静态,会发生什么?哪种方法最好?如果我将事物变为静态,我是否会失去mut?

+5

您正在使用'Lock'错误。鉴于此,使用'synchronized'。或阅读更多。多得多。 –

+2

另外,不要'扩展线程'。 –

+1

另外,格式化您的代码。请。这几乎是难以辨认的。 –

回答

2

在Java中​​部分是可重入的。这意味着单个线程可以根据需要多次进入同步部分,但只有在没有其他线程存在时才能进入新线程。当前在这些部分中的线程已经获得一个锁,并且仅在离开所有同步部分时才返回锁。除了通过方法签名来声明​​之外,​​也可以直接在对象上调用。例如;这两种方法都会有同样的效果:

synchronized public void foo() { 

} 

public void foo() { 
    synchronized(this) { 

    } 
} 

ReentrantLock是只有一个线程非常相似,​​可以同时获取锁。如果一个线程到达lock.lock()语句,它将等待,直到锁被另一个线程解锁。如果线程已经锁定,它将继续。在单个同步代码块不够用的更复杂情况下,这可能非常有用。

会发生什么,如果...我使put方法同步和静态?

如果方法是static synchronized这意味着您正在锁定类本身而不是类的实例。它独立于实例​​方法被锁定。


为您的代码:

在这里做最简单的事情将是使Data对象转换为线程安全的对象。如果你不能编辑这个类的代码,那么一个有效的策略就是将这个对象包装在一个线程安全的包装器中。

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); 
+1

谢谢你关于'static synchronized'的回答,因为我在做什么我可以编辑这个类,这样应该没问题。欣赏它:) – I2obiN