简体   繁体   中英

Could "correctly synchronized" be applied to a class instead of the whole program?

There is a term correctly synchronized in the JLS :

A program is correctly synchronized if and only if all sequentially consistent executions are free of data races.

If a program is correctly synchronized, then all executions of the program will appear to be sequentially consistent (§17.4.3).

Can this correctly synchronized be applied to something smaller than the whole program, like some collection class?

In other words, imagine that I want to create my custom concurrent collection class.
I want the code of my collection to never produce data races in any program which uses my collection.
Would it be enough to only check that every possible sequential execution has no data races in order to guarantee that non-sequential executions also cannot produce data races?

You need to ensure that there would be no race conditions is your concurrent custom collection.

Ie multiple threads can access the same element simultaneously only if they are trying to read its value, that's fine. But if it's possible if one thread is trying to update the element while another is trying to retrieve its value, or multiple threads a trying to change the same element at the same time (overriding results produced by one-another), that's a problem. And it can be avoided by synchronizing the mutating code.

§17.4.5. Happens-before Order

When a program contains two conflicting accesses (§17.4.1) that are not ordered by a happens-before relationship, it is said to contain a data race .

§17.4.1. Shared Variables

Two accesses to (reads of or writes to) the same variable are said to be conflicting if at least one of the accesses is a write .

Here's a dummy example of the concurrent list which allows reading its value from multiple threads simultaneously, but if one of the threads is writing a value, all others would be blocked.

This can be achieved by using ReentrantReadWriteLock .

public class MyConcurrentArrayList<T> {
    private Object[] array;
    private int size;
    
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Lock read = lock.readLock();
    private final Lock write = lock.readLock();
    
    // non-mutating operation
    @SuppressWarnings("unchecked")
    public T get(int i) {
        T result;
        
        read.lock(); // lock the read-lock, from that moment only non-mutating operations (guarded by the readLock) are allowed
        // access the element under the given index
        try {
            result = (T) array[i];
        } finally {
            read.unlock(); // release the read-lock
        }
        return result;
    }
    
    // mutating operation
    public void add(T item) {
        write.lock(); // lock the write-lock, none of the threads would be able to read or update the list until this lock is not released
        
        try {
            // check if the list needs to grow (omitted)

            array[size++] = item; // add a new element
        } finally {
            write.unlock(); // release the write-lock
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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