首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java中的线程安全性

java中的线程安全性
EN

Stack Overflow用户
提问于 2010-10-08 22:16:23
回答 5查看 515关注 0票数 1

全,

在过去的几天里,我开始学习Java线程,只读到一些场景,即使使用了同步器方法/块,代码/类仍然容易受到并发问题的影响。有没有人能提供一个同步块/方法失败的场景?而且,在这些情况下,应该有什么替代方案来确保线程安全。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-10-08 22:24:33

“易受并发问题的影响”是非常模糊的。它将有助于了解您实际阅读的内容和位置。脑海中浮现出两件事:

  • 只是在某处使用" synchronized“并不意味着代码被正确地同步了--这可能很难做到,而且开发人员经常会错过一些有问题的场景,即使他们认为他们做的是对的。
  • 即使同步正确地防止了对数据的不确定性更改,您仍然可能遇到deadlocks.
票数 0
EN

Stack Overflow用户

发布于 2010-10-08 22:24:08

并发访问下的正确行为是一个复杂的主题,它不像在所有东西上都打synchronized那么简单,因为现在您必须考虑操作可能如何交错。

例如,假设你有一个像list这样的类,你想让它成为threadsafe。因此,您可以使所有方法同步并继续。很可能,客户端可能会以以下方式使用您的列表:

代码语言:javascript
复制
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类指定它总是在自己的监视器上同步,那么这种特定的情况可以被修复为

代码语言:javascript
复制
synchronized(list)
{
    if (list.size() > index)
    {
        return list.get(index);
    }
}

但在其他同步方案下,这是行不通的。或者它可能是一个太多的瓶颈。或者强制客户端在同一词法范围内进行多个调用可能是不可接受的约束。这完全取决于你试图实现的目标,比如如何让你的界面变得安全、高效和优雅。

票数 3
EN

Stack Overflow用户

发布于 2010-10-08 22:23:02

场景1经典死锁:

代码语言:javascript
复制
Object Mutex1;
Object Mutex2;


public void method1(){
    synchronized(Mutex1){
        synchronized(Mutex2){
        }
    }
}

public void method2(){
    synchronized(Mutex2){
        synchronized(Mutex1){
        }
    }
}

其他场景包括共享资源的任何内容,甚至包括变量,因为一个线程可以更改变量的内容,甚至可以在另一个线程不知道的情况下使其指向null。写入IO也有类似的问题,请尝试使用两个线程将代码写入文件,或将代码写入套接字。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3891454

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档