I2o*_*biN 2 java concurrency multithreading locks
假设我有一台具有多个线程的服务器,这些线程共享对Data实例的引用。快速例如
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(); }
}
}
Run Code Online (Sandbox Code Playgroud)
像上面那样使用锁,还是像下面那样同步put方法,
class Data {
private LinkedList<String> data = new LinkedList<String>();
synchronized void put(String x){ data.add(x); }
}
Run Code Online (Sandbox Code Playgroud)
这很粗糙
我主要只是担心并发性。
使用同步方法,假设同步将发生在类的“数据”实例/对象上,我是否正确?因此,一个UploadThread可以调用put过程/方法,而一个ReadThread可以并行执行相同的操作。但是,使用ReentrantLock示例,任何时候只有一个线程能够执行put调用?
如果在“数据”类中将LinkedList设置为静态,将put方法同步并设置为静态,会发生什么情况?哪种方法最好?如果我使事物静止,我会失去mut ex吗?
在Java中,synchronized各部分是可重入的。这意味着单个线程可以根据需要多次进入同步部分,但是只有在不存在其他线程时才可以进入新线程。当前在这些部分中的线程已获取了锁定,并且仅在离开所有同步部分后才返回该锁定。除了synchronized通过方法签名声明之外,synchronized还可以直接在对象上调用。例如; 这两种方法将具有相同的效果:
synchronized public void foo() {
}
public void foo() {
synchronized(this) {
}
}
Run Code Online (Sandbox Code Playgroud)
与ReentrantLock非常相似synchronized,因为一次只有一个线程可以获取锁。如果一个线程到达一条lock.lock()语句,它将等待直到另一个线程将锁解锁。如果线程已经具有锁,它将继续。这在单个同步代码块还不够的更复杂情况下很有用。
如果...使同步同步和静态放置方法会怎样?
如果方法是static synchronized,则意味着您要锁定类本身而不是该类的实例。它独立于实例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);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2448 次 |
| 最近记录: |