Java线程同步块行为 - synchronized与synchronized()?

时间:2013-03-13 11:16:00

标签: java multithreading thread-safety

我有简单的问题,但有问题可以找到答案。

问题是,如果synchronized方法等于synchronized(this) - 意味着执行相同的锁定。

我想编写线程安全的代码,减少线程锁定(不想使用始终同步的方法,但有时只使用部分同步关键部分)。

如果这段代码是否相同,你可以解释一下吗?为什么用简短的话来说(简化例子来说明原子问题)?

实施例

此混合锁定代码是否等于下面的强力代码:

public class SynchroMixed {
    int counter = 0;

    synchronized void writer() {
        // some not locked code
        int newCounter = counter + 1;

        // critical section
        synchronized(this) {
            counter = newCounter;
        }
    }

    synchronized int reader() {
        return counter;
    }
}

暴力代码(每个方法都被锁定,包括非关键部分:

public class SynchroSame {
    int counter = 0;

    synchronized void writer() {
        int newCounter = counter + 1;

        counter = newCounter;
    }

    synchronized int reader() {
        return counter;
    }
}

或者我应该写这段代码(这肯定是有效但更微观的编码和不清楚)。

public class SynchroMicro {
    int counter = 0;

    void writer() {
        // some not locked code
        int newCounter = counter + 1;

        // critical section
        synchronized(this) {
            counter = newCounter;
        }
    }

    int reader() {
        synchronized (this) {
            return counter;
        }
    }
}

4 个答案:

答案 0 :(得分:3)

synchronized方法和synchronized(this)意味着绝对相同,并使用相同的互斥锁。这是一个更喜欢品味的问题。

我个人更喜欢synchronized(this),因为它明确指定互斥锁的范围,它可能小于整个方法

答案 1 :(得分:2)

synchronized(this)方法中的synchronized肯定没有意义,因为输入方法已隐式synchronized(this)

由于您明确打算缩小关键部分的范围,这只是一个语法错误,但缩小范围会在您的代码中引入数据争用:您必须读取和< em>在同一synchronized块中写共享变量。

此外,即使方法读取共享变量,仍然必须在synchronized块中执行此操作;否则它可能永远不会观察到其他线程的任何写入。这是Java内存模型的基本语义。

现在,如果您展示的内容确实代表了您的完整问题,那么您甚至不应该使用synchronized,而应使用简单的AtomicInteger,它将具有最佳的并发性能。< / p>

答案 2 :(得分:2)

这三个例子都是等价的。在方法上使用synchronized与在synchronized(this) {}内包装整个正文相同。

然后,通过对某些语句使用synchronized(this) {},线程只重新获取它已经拥有的锁:这里没有意义。

答案 3 :(得分:2)

从功能的角度来看,同步方法和块绝对相似。它们都执行相同的任务,即避免同时访问方法中的特定方法或代码块。

当你有一个很长的方法并且只需要一部分同步时,

synchronized()块更灵活,更方便。您无需锁定对整个方法的访问权限,因为我们知道同步存在一些与之相关的性能问题。因此,始终建议同步只需要部分代码而不是整个方法(如果不需要)。