Luc*_*cky 12 java multithreading synchronization
在我的java项目中,我写的几乎所有非静态方法都是synchronized
.我今天决定通过删除大多数synchronized
关键字来修复一些代码.就在那里,我创建了几个线程问题,需要花费很长时间来修复,而不会增加性能.最后我恢复了一切.
我没有看到其他人在任何地方用" synchronized
" 编写代码.那么,有没有任何理由,我不应该有" synchronized
"无处不在?
如果我不太关心性能(即,该方法每隔几秒不被调用一次)怎么办?
akf*_*akf 36
如果不加选择地同步,则还存在创建死锁的风险.
假设我有两个类,Foo
并且Bar
都有一个synchronized方法doSomething()
.进一步假设每个类都有一个synchronized方法,将另一个类的实例作为参数.
public class Foo {
synchronized void doSomething() {
//code to doSomething
}
synchronized void doSomethingWithBar(Bar b) {
b.doSomething();
}
}
public class Bar {
synchronized void doSomething() {
//code to doSomething
}
synchronized void doSomethingWithFoo(Foo f) {
f.doSomething();
}
}
Run Code Online (Sandbox Code Playgroud)
你可以看到,如果你有一个实例Foo
和一个实例Bar
,两者都试图同时doSomethingWith*
在彼此之间执行它们的方法,就会发生死锁.
要强制死锁,可以在两个doSomethingWith*
方法中插入一个sleep (使用Foo
示例):
synchronized void doSomethingWithBar(Bar b) {
try {
Thread.sleep(10000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
b.doSomething();
}
Run Code Online (Sandbox Code Playgroud)
在main方法中,您启动两个线程来完成示例:
public static void main(String[] args) {
final Foo f = new Foo();
final Bar b = new Bar();
new Thread(new Runnable() {
public void run() {
f.doSomethingWithBar(b);
}
}).start();
new Thread(new Runnable() {
public void run() {
b.doSomethingWithFoo(f);
}
}).start();
}
Run Code Online (Sandbox Code Playgroud)
duf*_*ymo 27
当然 - 表现.监视器需要付费.
答案既不是随机删除也不是以随机方式添加同步.最好阅读Brian Goetz的"Java Concurrency In Practice"或Doug Lea的"Java Threads"等书籍,以了解如何正确地完成它.当然,要好好学习新的并发软件包.
多线程比synchronized关键字要多得多.
Jar*_*Par 13
如果你认为在任何地方放置"synchronized"关键字是一个很好的解决方案,即使忽略了性能,那么你也不能确切地理解发生了什么,你不应该使用它.我强烈建议在没有指导的情况下深入研究这个主题.
线程是一个非常难以掌握的主题,理解你为什么要做的事情非常重要.否则你将会遇到很多代码而不是设计的代码.这最终会让你感到痛苦.
表现点已经说明了.
另外,请记住,所有线程都会获得堆栈的不同副本.因此,如果方法仅使用在该方法内创建的变量,并且无法访问外部世界(例如文件句柄,套接字,数据库连接等),则不会出现线程问题.
比放在synchronized
任何地方要好得多的是仔细推理你的类所需的不变量,然后同步足以确保那些不变量.如果过度同步,则会产生两个风险:
死锁每个人都知道.活动问题与同步成本无关,而是与全局同步多线程应用程序中的所有内容相关的事实,然后许多线程将被阻塞等待获取监视器,因为另一个线程正在触及不相关的东西但使用相同的东西监控.
如果你想在任何地方拍一个关键字以确保安全,那么我建议使用final
而不是synchronized
. :)
您可以做的任何事情都final
有助于提高线程安全性,并更容易推理锁定需要维护的不变量.举个例子,假设你有这个琐碎的课程:
public class SimpleClass {
private volatile int min, max;
private volatile Date startTime;
// Assume there are many other class members
public SimpleClass(final int min, final int max) {
this.min = min;
this.max = max;
}
public void setMin(final int min) {
// set min and verify that min <= max
}
public void setMax(final int max) {
// set max and verify that min <= max
}
public Date getStartTime() {
return startTime;
}
}
Run Code Online (Sandbox Code Playgroud)
使用上面的类,设置min或max时,需要同步.上面的代码被破坏了.这门课有什么不变量?您需要min <= max
始终确保即使多个线程正在调用setMin
或setMax
.
假设这是一个包含许多变量的大类并且您同步所有内容,那么如果一个线程调用setMin
并且另一个线程调用getStartTime
,则第二个线程将被不必要地阻塞直到setMin
返回.如果你用一个有很多成员的类来做这个,并且假设只有少数成员参与必须保护的不变量,那么同步所有内容将导致这种类型的许多活跃问题.
归档时间: |
|
查看次数: |
1769 次 |
最近记录: |