Java Concurrency - a combination of objects

Visibility

Visibility is quite subtle errors that occur could differ materially from intuition. In single-threaded environment, the value of a variable is written, and then read the value in the absence of intervention, you would naturally want the same value. But when reading and writing take place in a different thread, the situation may not be the same. In order to ensure the visibility of memory across threads, you must use synchronization mechanisms.

public class NonVisibility {

	static boolean ready = false;
	static int num = 0;

	static class ReadThread extends Thread {
		@Override
		public void run() {
			while (!ready) {
				Thread.yield();
			}
			System.err.println(num);
		}
	}

	public static void main(String[] args) {
		new ReadThread().start();
		num = 42;
		ready = true;
	}
}
复制代码

** "reordering" ** phenomenon, in a single thread, so long as no impact on the results, we can not guarantee that the operation will be strictly enforced in accordance with the written order given - even if reordering impact on other threads.

Expired data

In NonVisibility, the expiration data cause print errors in a production environment, program expiration value may crash, resulting in dirty data, the calculated error or infinite loop.

Non-atomic operation 64

The non-volitile long and double data allows the JVM separated into two 32-bit operation, then use volitile or synchronization mechanisms can be solved.

Lock and visibility

Built-in lock can be used to ensure that one thread to see the impact of another thread in some predictable manner, when A and B performing the same lock monitoring of sync blocks, the sync block A before doing things, both of B It is visible. Without synchronization, there is no such guarantee.

锁不仅仅是同步互斥的,也可以是内存可见的。
为了保证所有线程都能看到共享的、可变变量的最新值,读取和写入线程必须使用公共的锁进行同步。
复制代码

{% Asset_img 1561172279707.png ensure visibility synchronous%}

volitile variable

When a field is declared after the volatile type, and the compiler will monitor this variable runtime: it is shared, its operation will not be reordered with other memory operations. volatile variables are not cached in processor registers or elsewhere. So when reading a volatile variable always returns the latest data.

Understanding the volatile variables, the following code is conceivable which functions substantially similar. Substituted only get and set methods for the read and write operations volatile variables. But access to volatile variables operation does not lock, there will not be blocking the thread of execution, so volatile in terms of the relative sychronized just a lightweight synchronization mechanism.

public int value;
public sychronized int get() {
	return value;
}
public sychronized void set(int value) {
	this.value = value;
}
复制代码

Seen from the perspective of memory to see, write volatile variable is like out of the sync blocks, reading a volatile variable is like entering synchronized blocks. It is not recommended rely on volatile variables to control visibility, volatile extremely fragile and not intuitive.

只有当volatile变量能够简化实现和同步策略的验证,才使用它们。
正确使用volatile变量的方式:
用于确保它们所引用的对象状态的可见性,或者用于表示重要的生命周期事件的发生。
复制代码

volatile variable aspect of course, but there are limitations. As it is usually volatile identification is completed, interrupt, using state of the mark. Use extreme caution must be volatile, such as volatile can not let the increment operator (count ++) atomization, unless there is only one thread to operate.

加锁可以保证可见性和原子性,但是volatile只能保证可见性。
复制代码

Publishing and overflow

An object release (publish) which is capable of being used outside the current extent of the code. But also a need to ensure that the internal state of an object is not exposed. If the variable has released internal state may endanger encapsulation, and the program is difficult to maintain stable; if you publish an object, is not yet complete construction, also endanger the security thread. An object is not yet ready to be published, it is called overflow. The following is an example of an object overflow.

// 发布对象
public static final Map<Integer, String> map;
public void init() {
	map = new HashMap<>();
}
复制代码
// 允许内部可变数据溢出
class UsafeState{
    private String[] states = new String[]{"XA", "TCC"};
    public String[] getStates() {
        return states;
    }
}
复制代码
// 隐式地允许this引用溢出,因为内部被包含了隐式的引用
class Escape {
    public Escape(EventSource source) {
   		source.addEventListener(new EventListener() {
          	public void onClick(Event event) {
                doSomethine(event);
            }  
        });    
    }
}
复制代码

Security building practices

As the object in the constructor returns, is a predictable, stable state. If this quote overflow during construction, such objects are considered "not properly constructed."

不要让this引用在构造期间溢出。
复制代码

A common cause of this common reference error during the construction of overflow, is to start a thread in the constructor. Either (passing through it to the constructor) or implicit, this reference is almost always a new thread shared display. In the constructor creates a thread is not wrong, but it is best not to start it, be started at the end of the constructor by a start method.

If you want to increase the listening or start a thread in the constructor, you can use a private function or factory method.

public class SafeListener {
    private final EventListener listener;
    public SafeListener() {
        this.listener = new EventListener() {
            public void onClick(Event e) {
                doSomethin(e);
            }
        };
    }
    public static SafeListener newInstance(EventSource source) {
        SafeListener sl = new SafeListener();
        source.addListener(sl.listener);
        return sl;
    }
}
复制代码

Thread closed

Thread closed is one of the easiest ways to achieve thread-safe. When the object is enclosed in a thread, a practice known as automatic thread-safe.

Swing development thread sealing technique. Swing visual components and data model is not thread-safe, thread-safety achieved by limiting them to the event dispatch thread in Swing.

Ad-hoc thread limit

It refers to the maintenance thread restrictive task falls on all achieve. Because there is no visibility modifiers and language features such as local variables will help limit the objects in the target thread, so this method is error-prone. In view of the ad-hoc thread limit has vulnerability, it should be used sparingly. (Stack limit or the ThreadLocal) replace it with a strong thread form of limitation.

The stack limit is a special case of thread limit, the target can only be touched by a local variable. Other threads can not access. Compared with the ad-hoc easier to maintain and more robust.

public int loadTheArk(Collection<Animal> candidates) {
	SortedSet<Animal> animals;
    int numPairs=0;
    // animals 限制在方法中,不要让它们逸出!
    animals = new TreeSet<>();
    animals.addAll(candidates);
    .....
}
复制代码

Maintenance stack limit object reference, it is necessary to ensure that there is no escaping the object reference. The context of the use of non-thread-safe internal thread object can still ensure the security thread. But the first-line development tasks encode the moment need to be aware of the document, and to prevent post-maintenance personnel error of letting the object overflow.

ThreadLocal

EXAMPLE single variable or global variables commonly used design, sharing occurs. Each thread maintains a single variable, so you can prevent concurrency issues.

private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<>() {
	public Connection initialValue() {
		return DriverManager.getConnection(DB_URL);
	}
}
public static Connection getConnection() {
	return connectionHolder.get();
}
复制代码

In the ByteBuf in Netty, it is the use of ThreadLocal to be allocated byte array, accept the request to prevent the frequent create a byte array, so we can save memory, but also concurrency issues.

ThreadLocal very easy to abuse: for example, they will be closed as the data permit global variables. Thread local variables will reduce reuse, the introduction of coupling between classes obscure, should use caution.

Immutability

Immutable objects will always be thread-safe. The final keyword is part of the constitution of immutable objects, modified final object is still likely to be variable.

FOR IMMEDIATE RELEASE When not using synchronization objects, immutable objects can still be safely accessed.

Safe release mode

  • Static initialization generated objects.
  • Reference is stored in the volatile or AtomicReference.
  • Referring to the right to the final storage domain.
  • Reference is stored by the lock properly protected domain.

Efficient immutable objects

An object is not technically immutable, but its status will not change after the release, is called the effective immutable objects.

// Date本身是可变的,把它当做不可变对象就可以忽略锁。
// 放入到同步化的Map中访问Date就不需要考虑同步的问题了。
Collections.sychronizedMap(new HashMap<String, Date>);
复制代码

Guess you like

Origin juejin.im/post/5d1b1413f265da1bcc195bb0