全,
在过去的几天里,我开始学习Java线程,只读到一些场景,即使使用了同步器方法/块,代码/类仍然容易受到并发问题的影响。有没有人能提供一个同步块/方法失败的场景?而且,在这些情况下,应该有什么替代方案来确保线程安全。
发布于 2010-10-08 22:24:33
“易受并发问题的影响”是非常模糊的。它将有助于了解您实际阅读的内容和位置。脑海中浮现出两件事:
发布于 2010-10-08 22:24:08
并发访问下的正确行为是一个复杂的主题,它不像在所有东西上都打synchronized那么简单,因为现在您必须考虑操作可能如何交错。
例如,假设你有一个像list这样的类,你想让它成为threadsafe。因此,您可以使所有方法同步并继续。很可能,客户端可能会以以下方式使用您的列表:
int index = ...; // this gets set somewhere, maybe passed in as an argument
// Check that the list has enough elements for this call to make sense
if (list.size() > index)
{
return list.get(index);
}
else
{
return DEFAULT_VALUE;
}在单线程环境中,这段代码是完全安全的。但是,如果列表正在被并发地访问(并且可能被修改),那么列表的大小可能会在调用size()之后更改,但在调用get()之前更改为。因此,在这种情况下,list可能会“不可能”抛出一个IndexOutOfBoundsException (或类似的),即使事先检查了大小。
如何解决这个问题没有捷径--你只需要仔细考虑你的类/接口的用例,并确保在与任何其他有效操作交错时,你可以实际保证它们。通常,这可能需要一些额外的复杂性,或者只是文档中的更多细节。如果假设的list类指定它总是在自己的监视器上同步,那么这种特定的情况可以被修复为
synchronized(list)
{
if (list.size() > index)
{
return list.get(index);
}
}但在其他同步方案下,这是行不通的。或者它可能是一个太多的瓶颈。或者强制客户端在同一词法范围内进行多个调用可能是不可接受的约束。这完全取决于你试图实现的目标,比如如何让你的界面变得安全、高效和优雅。
发布于 2010-10-08 22:23:02
场景1经典死锁:
Object Mutex1;
Object Mutex2;
public void method1(){
synchronized(Mutex1){
synchronized(Mutex2){
}
}
}
public void method2(){
synchronized(Mutex2){
synchronized(Mutex1){
}
}
}其他场景包括共享资源的任何内容,甚至包括变量,因为一个线程可以更改变量的内容,甚至可以在另一个线程不知道的情况下使其指向null。写入IO也有类似的问题,请尝试使用两个线程将代码写入文件,或将代码写入套接字。
https://stackoverflow.com/questions/3891454
复制相似问题