Андрей Козицкий Asked:2020-06-27 02:33:29 +0800 CST2020-06-27 02:33:29 +0800 CST 2020-06-27 02:33:29 +0800 CST 多线程同步 772 据我所知,关键字synchronize会使方法的执行速度减慢几十甚至几百倍,是什么导致了如此巨大的速度损失,有没有线程同步的类似物? java 3 个回答 Voted Sergey Gornostaev 2020-06-27T15:40:10+08:002020-06-27T15:40:10+08:00 正如其他答案已经指出的那样,减速的主要原因是同步方法/块一次只能执行一个线程,而其他线程必须等待。但是还有其他因素对减速的影响要小得多,但在具有高性能要求的算法中仍然很明显。第一个这样的因素是监视器捕获/释放操作的开销。对于有偏见的监视器,它们是最小的——它们适合一些硬件指令,但在竞争激烈的情况下,虚拟机必须执行更多的操作。包括涉及导致上下文切换的系统调用的操作。第二个因素是安全点. 在 HotSpot 的情况下,它们只能是全局的,因此对监视器进行充气/放气会暂时停止所有 JVM 线程,包括服务线程。第三个因素,甚至更底层,是在捕获监视器时需要使用内存屏障。这减少了重新排序优化的可能性,并迫使处理器处理缓存同步。 因此,在编写多线程程序时,尽可能减少共享状态的使用或使其不可变非常重要。不变性和限制是最好的同步选择。 Best Answer Komdosh 2020-06-27T02:42:55+08:002020-06-27T02:42:55+08:00 损失只发生在多线程环境中,在单线程上没有区别。事实上,要执行synchronized一个块,所有线程都必须到达它的开始位置,然后依次synchronized在一个线程上执行该块。 不可能明确地回答有关同步类似物的问题,这个问题太笼统了,并且根据数据和实现的不同而有很大差异,有阻塞算法,有非阻塞事务内存。在这种情况下,已经有必要了解具体的任务,数据的呈现方式和处理方式,理想情况下,所有数据都应该独立处理,那么就不需要同步流。 Turalllb 2020-06-27T03:43:47+08:002020-06-27T03:43:47+08:00 锁通过一次只允许一个线程执行该代码来保护一段代码。 锁控制试图进入受保护代码段的线程。 每个条件对象管理已进入受保护代码段但还不能执行工作的线程。 运行一个线程必须依次访问的代码块花费的时间越长,情况就越糟糕。但是,如果这真的是无法从多个线程同时处理的代码,那么就没有其他出路了。我们需要同步。关键字synchronize只是 Java 的一个方便的工具。如果有很多类似的代码,那么最好使用更灵活的工具。Java SE 5.0 中添加了Lock和接口Condition,为程序员提供了对锁的高度控制。 在 Java 中还有一个关键字volatile允许一个线程同时处理一个变量。你可以在这里阅读一些陷阱,还有一篇很好的文章,你可以从中了解它是如何工作的。 Java中的同步词“在手指上” 我认为应该清楚的是,如果这是一个由数千个客户端访问的服务器,并且有一些元素不能被多个客户端同时更改,那么您将不得不排队。如果它是一个代码块被访问的应用程序,例如由 8 个线程访问,则相同。一段代码,假设它在 1 秒内运行。相反,所有线程将在 8 秒多一点的时间内完成它。这当然不是一个确切的解释,但现在这已经足够了。值得知道的是,如果需要同步,那么它可以synchronize使代码更具可读性,但会影响全局,可能还会影响不需要同步的代码部分。或使用其他工具进行点冲击。
正如其他答案已经指出的那样,减速的主要原因是同步方法/块一次只能执行一个线程,而其他线程必须等待。但是还有其他因素对减速的影响要小得多,但在具有高性能要求的算法中仍然很明显。第一个这样的因素是监视器捕获/释放操作的开销。对于有偏见的监视器,它们是最小的——它们适合一些硬件指令,但在竞争激烈的情况下,虚拟机必须执行更多的操作。包括涉及导致上下文切换的系统调用的操作。第二个因素是安全点. 在 HotSpot 的情况下,它们只能是全局的,因此对监视器进行充气/放气会暂时停止所有 JVM 线程,包括服务线程。第三个因素,甚至更底层,是在捕获监视器时需要使用内存屏障。这减少了重新排序优化的可能性,并迫使处理器处理缓存同步。
因此,在编写多线程程序时,尽可能减少共享状态的使用或使其不可变非常重要。不变性和限制是最好的同步选择。
损失只发生在多线程环境中,在单线程上没有区别。事实上,要执行
synchronized
一个块,所有线程都必须到达它的开始位置,然后依次synchronized
在一个线程上执行该块。不可能明确地回答有关同步类似物的问题,这个问题太笼统了,并且根据数据和实现的不同而有很大差异,有阻塞算法,有非阻塞事务内存。在这种情况下,已经有必要了解具体的任务,数据的呈现方式和处理方式,理想情况下,所有数据都应该独立处理,那么就不需要同步流。
锁通过一次只允许一个线程执行该代码来保护一段代码。
锁控制试图进入受保护代码段的线程。
每个条件对象管理已进入受保护代码段但还不能执行工作的线程。
运行一个线程必须依次访问的代码块花费的时间越长,情况就越糟糕。但是,如果这真的是无法从多个线程同时处理的代码,那么就没有其他出路了。我们需要同步。关键字
synchronize
只是 Java 的一个方便的工具。如果有很多类似的代码,那么最好使用更灵活的工具。Java SE 5.0 中添加了Lock
和接口Condition
,为程序员提供了对锁的高度控制。在 Java 中还有一个关键字
volatile
允许一个线程同时处理一个变量。你可以在这里阅读一些陷阱,还有一篇很好的文章,你可以从中了解它是如何工作的。Java中的同步词“在手指上”
我认为应该清楚的是,如果这是一个由数千个客户端访问的服务器,并且有一些元素不能被多个客户端同时更改,那么您将不得不排队。如果它是一个代码块被访问的应用程序,例如由 8 个线程访问,则相同。一段代码,假设它在 1 秒内运行。相反,所有线程将在 8 秒多一点的时间内完成它。这当然不是一个确切的解释,但现在这已经足够了。值得知道的是,如果需要同步,那么它可以
synchronize
使代码更具可读性,但会影响全局,可能还会影响不需要同步的代码部分。或使用其他工具进行点冲击。