简体   繁体   English

线程安全程序的方法

[英]Approach to a thread safe program

All, 所有,

What should be the approach to writing a thread safe program. 编写线程安全程序的方法应该是什么? Given a problem statement, my perspective is: 给定一个问题陈述,我的观点是:

1 > Start of with writing the code for a single threaded environment. 1>开始为单线程环境编写代码。
2 > Underline the fields which would need atomicity and replace with possible concurrent classes 2>在需要原子性的字段下划线,并用可能的并发类替换
3 > Underline the critical section and enclose them in synchronized 3>在关键部分加上下划线,并将其同步
4 > Perform test for deadlocks 4>执行死锁测试

Does anyone have any suggestions on the other approaches or improvements to my approach. 是否有人对其他方法有任何建议或对我的方法有所改进。 So far, I can see myself enclosing most of the code in synchronized blocks and I am sure this is not correct. 到目前为止,我可以看到自己将大多数代码包含在同步块中,并且我确信这是不正确的。

Programming in Java 用Java编程

Writing correct multi-threaded code is hard, and there is not a magic formula or set of steps that will get you there. 编写正确的多线程代码很困难,并且没有神奇的公式或步骤集可以帮助您实现目标。 But, there are some guidelines you can follow. 但是,您可以遵循一些准则。

Personally I wouldn't start with writing code for a single threaded environment and then converting it to multi-threaded. 我个人不会先为单线程环境编写代码,然后再将其转换为多线程。 Good multi-threaded code is designed with multi-threading in mind from the start. 好的多线程代码从一开始就考虑了多线程的设计。 Atomicity of fields is just one element of concurrent code. 字段的原子性只是并发代码的一个元素。

You should decide on what areas of the code need to be multi-threaded (in a multi-threaded app, typically not everything needs to be threadsafe). 您应该确定代码的哪些区域需要多线程(在多线程应用程序中,通常并非所有内容都需要线程安全)。 Then you need to design how those sections will be threadsafe. 然后,您需要设计这些部分如何是线程安全的。 Methods of making one area of the code threadsafe may be different than making other areas different. 使代码的一个区域为线程安全的方法可能不同于使其他区域为不同的方法。 For example, understanding whether there will be a high volume of reading vs writing is important and might affect the types of locks you use to protect the data. 例如,了解是否会有大量的读写操作很重要,并且可能会影响您用来保护数据的锁的类型。

Immutability is also a key element of threadsafe code. 不变性也是线程安全代码的关键要素。 When elements are immutable (ie cannot be changed), you don't need to worry about multiple threads modifying them since they cannot be changed. 当元素是不可变的(即无法更改)时,您不必担心多个线程会对其进行修改,因为它们无法更改。 This can greatly simplify thread safety issues and allow you to focus on where you will have multiple data readers and writers. 这可以大大简化线程安全问题,并使您可以专注于将拥有多个数据读取器和写入器的位置。

Understanding details of concurrency in Java (and details of the Java memory model) is very important. 了解Java中的并发细节(以及Java内存模型的细节)非常重要。 If you're not already familiar with these concepts, I recommend reading Java Concurrency In Practice http://www.javaconcurrencyinpractice.com/ . 如果您还不熟悉这些概念,建议阅读http://www.javaconcurrencyinpractice.com/上的 Java Concurrency in Practice。

You should use final and immutable fields wherever possible, any other data that you want to change add inside: 您应该尽可能使用final不可变字段,您要更改的任何其他数据都将添加到内部:

  synchronized (this) {
     // update
  }

And remember, sometimes stuff brakes, and if that happens, you don't want to prolong the program execution by taking every possible way to counter it - instead "fail fast". 记住,有时会刹车,如果发生这种情况,您不想通过采取一切可能的方法来反击它来延长程序的执行时间,而是“快速失败”。

As you have asked about "thread-safety" and not concurrent performance, then your approach is essentially sound. 当您询问“线程安全性”而不是并发性能时,您的方法本质上是合理的。 However, a thread-safe program that uses synchronisation probably does not scale much in a multi cpu environment with any level of contention on your structure/program. 但是,使用同步的线程安全程序在结构/程序上存在任何争用级别的多cpu环境中可能不会扩展太多。

Personally I like to try and identify the highest level state changes and try and think about how to make them atomic, and have the state changes move from one immutable state to another – copy-on-write if you like. 就我个人而言,我喜欢尝试确定最高级别的状态更改,并尝试考虑如何使它们变为原子状态,并让状态更改从一种不变的状态转移到另一种不变的状态–如果您愿意的话,可以写时复制。 Then the actual write can be either a compare-and-set operation on an atomic variable or a synchronised update or whatever strategy works/performs best (as long as it safely publishes the new state). 然后,实际写操作可以是对原子变量进行比较并设置操作,也可以是同步更新,也可以是最有效/最有效的策略(只要可以安全地发布新状态)即可。

This can be a bit difficult to structure if your new state is quite different (requires updates to several fields for instance), but I have seen it very successfully solve concurrent performance issues with synchronised access. 如果您的新状态完全不同(例如,需要更新多个字段),那么结构可能会有些困难,但是我已经看到它非常成功地解决了同步访问带来的并发性能问题。

购买并阅读Brian Goetz的“实践中的Java并发性”。

可能同时由多个线程访问的任何变量(内存)都需要使用同步机制进行保护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM