Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否存在Java synchronized关键字优于Atomics的可行用例?_Java_Atomic_Synchronized - Fatal编程技术网

是否存在Java synchronized关键字优于Atomics的可行用例?

是否存在Java synchronized关键字优于Atomics的可行用例?,java,atomic,synchronized,Java,Atomic,Synchronized,我在线程方面没有太多经验,但我用Atomics编写了一个漂亮的非阻塞顺序Id生成器。。。。这使我在测试中获得了非常显著的性能提升。现在我想知道为什么有人会使用synchronized,因为它速度太慢了。。。现代64位多核硬件有什么原因吗?其他人现在问我关于原子的问题。我希望能够告诉他们永远不要使用那个关键词,除非他们正在部署到古老的硬件上 因为你不能只使用原子来执行多个操作(技术上你可以,因为你可以使用原子来实现一个“锁”,但我认为这不是重点)。您也不能使用原子来执行阻塞等待(您可以执行繁忙等待

我在线程方面没有太多经验,但我用Atomics编写了一个漂亮的非阻塞顺序Id生成器。。。。这使我在测试中获得了非常显著的性能提升。现在我想知道为什么有人会使用synchronized,因为它速度太慢了。。。现代64位多核硬件有什么原因吗?其他人现在问我关于原子的问题。我希望能够告诉他们永远不要使用那个关键词,除非他们正在部署到古老的硬件上

因为你不能只使用原子来执行多个操作(技术上你可以,因为你可以使用原子来实现一个“锁”,但我认为这不是重点)。您也不能使用原子来执行阻塞等待(您可以执行繁忙等待,但这几乎总是一个坏主意)


下面是OP的一个练习:编写一个程序,使用多个线程将时间戳日志消息写入同一个文件,其中消息必须以时间戳顺序显示在文件中。仅使用原子实现此功能,但无需重新发明ReentrantLock/synchronized。

取决于您正在做什么-如果您只需要原子提供的功能,那么是的,您不需要自己做同样的工作(使用synchronized关键字)。然而,许多多线程应用程序所做的事情比仅仅需要原子地增加一个数字要复杂得多


例如,在修改内存中的多个数据结构时,您可能需要一个工作单元,而所有这些都必须在不受干扰的情况下进行-您可以使用同步函数或块来实现这一点。

据我所知,synchronized关键字实际上是一个中等权重的递归(重入)锁

例如,以下(可怕的)代码不会死锁:

public static Object lock = new Object();

int recurCount = 0;

public int fLocktorial(int n) {
    synchronized(lock) {
        recurCount++;
        if (n <= 0)
            return 1;
        return n * fLocktorial(n-1);
    }
}
公共静态对象锁=新对象();
int recurCount=0;
公共国际植绒场(国际n){
已同步(锁定){
recurCount++;
如果(n)
现在我想知道为什么有人会使用synchronized,因为它速度太慢了

也许是因为速度不是一切

事实上,如果您客观地看待在实际应用程序上使用“漂亮”生成器的总体性能优势,我怀疑您会发现它太小而无关紧要

还有一个问题是你的基准测试是否真的有效;也就是说,你是否在做一些必要的事情来避免诸如JVM预热异常、优化异常等误导性影响,以及你是否(实际上)在衡量有争议和无争议的情况


是否存在Java synchronized关键字优于Atomics的可行用例

那很容易

任何需要独占访问一个或多个数据结构以执行一系列操作或本质上不安全的操作的情况。
AtomicXxx
类型不支持此类操作


我希望能够告诉他们永远不要使用那个关键词,除非他们正在部署到古老的硬件上


不要告诉他们。这是不正确的。事实上,如果您是Java线程的新手,我建议您在开始向人们提供建议之前阅读Goetz等人的“Java并发性实践”。

从概念上讲,受锁转换状态保护的关键部分从一个有效状态转换为另一个有效状态

int x, y;  // invariant: x==y

void inc()
    synchronized(lock)
        x++;
        y++;

void dec()
    ...
我们可以将状态封装在一个对象中,并以原子方式更改该对象

class State
    final int x, y;
    State(int x, y) { ... }

volatile State state;

void inc()
    do
        State s = state;
        State s2 = new State(s.x+1, s.y+1);
    while( ! compareAndSet( "state", s, s2) )  // use Unsafe or something

这更好吗?不一定。这很吸引人,而且当状态变得更复杂时会更简单;但在大多数情况下可能会更慢。

我不能将它们放在类中并使用原子引用类吗?…或者用原子布尔值保护if块吗?如果(…原子布尔值为true,则将其设置为false){…blah}AtomicReference仅保证您可以以原子方式获取/设置它。它不控制对实际对象本身的访问。在if…AtomicBoolean…上,执行if语句后会发生什么?一旦控制返回到函数,值可能会再次更改。从线程到线程的上下文切换可以(并且确实可以)任何时候都会发生,所以即使只有一行代码也足以让事情变得一团糟。我经历过很多次。实际上我不确定。compareAndSet方法是原子的,返回true或false…所以如果我把它放在if语句中,这不意味着我可以在if块中控制单线程访问吗?Might不是AtomicReference…可能是用于控制访问的AtomicBoolean。同一问题-compareAndSet()仅保证该函数(compareAndSet)内的原子性。if语句的其余部分和相关的代码块就是出现同步问题的地方。我建议用它写出一些代码的示例,然后记下如果它们与另一个线程中的另一行同时发生,哪些行会导致程序执行不稳定/错误的操作,即您可以帮助澄清。(如果您想进一步讨论,请编辑您的问题,以包含一个真实的示例。)我们在项目期间进行了一个实验,检查是否可以像这样使用if块。似乎原子调用的结果只返回给调用它的线程……或者至少我们无法诱使系统执行其他操作。因为该方法在另一个线程可以更改之前完成了整个过程其中的值在下一次线程尝试时返回的值不同。这至少是基于观察到的行为的理论。我会看看是否可以写一个例子。你不是第一个问的人。;-)你确定吗?关于:@user447607-关于它呢?公认的答案是一个繁忙的循环,这正是我所说的糟糕。试着运行这样一个程序,当它被“阻塞”时,看着它将你的cpu固定在100%