What does 'synchronized' mean?

2018-12-31 05:26发布

I have some questions regarding the usage and significance of the synchronized keyword.

  • What is the significance of the synchronized keyword?
  • When should methods be synchronized?
  • What does it mean programmatically and logically?

15条回答
梦该遗忘
2楼-- · 2018-12-31 05:43

What the other answers are missing is one important aspect: memory barriers. Thread synchronization basically consists of two parts: serialization and visibility. I advise everyone to google for "jvm memory barrier", as it is a non-trivial and extremely important topic (if you modify shared data accessed by multiple threads). Having done that, I advise looking at java.util.concurrent package's classes that help to avoid using explicit synchronization, which in turn helps keeping programs simple and efficient, maybe even preventing deadlocks.

One such example is ConcurrentLinkedDeque. Together with the command pattern it allows to create highly efficient worker threads by stuffing the commands into the concurrent queue -- no explicit synchronization needed, no deadlocks possible, no explicit sleep() necessary, just poll the queue by calling take().

In short: "memory synchronization" happens implicitly when you start a thread, a thread ends, you read a volatile variable, you unlock a monitor (leave a synchronized block/function) etc. This "synchronization" affects (in a sense "flushes") all writes done before that particular action. In the case of the aforementioned ConcurrentLinkedDeque, the documentation "says":

Memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a ConcurrentLinkedDeque happen-before actions subsequent to the access or removal of that element from the ConcurrentLinkedDeque in another thread.

This implicit behavior is a somewhat pernicious aspect because most Java programmers without much experience will just take a lot as given because of it. And then suddenly stumble over this thread after Java isn't doing what it is "supposed" to do in production where there is a different work load -- and it's pretty hard to test concurrency issues.

查看更多
君临天下
3楼-- · 2018-12-31 05:44

Here is an explanation from The Java Tutorials.

Consider the following code:

public class SynchronizedCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }
}

if count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:

  • First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
  • Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
查看更多
孤独寂梦人
4楼-- · 2018-12-31 05:45

Synchronized normal method equivalent to Synchronized statement (use this)

class A {
    public synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(this) {
             // all function code
        }
    } 
}

Synchronized static method equivalent to Synchronized statement (use class)

class A {
    public static synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(A.class) {
             // all function code
        }
    } 
}

Synchronized statement (using variable)

class A {
    private Object lock1 = new Object();

    public void methodA() {
        synchronized(lock1 ) {
             // all function code
        }
    } 
}

For synchronized, we have both Synchronized Methods and Synchronized Statements. However, Synchronized Methods is similar to Synchronized Statements so we just need to understand Synchronized Statements.

=> Basically, we will have

synchronized(object or class) { // object/class use to provides the intrinsic lock
   // code 
}

Here is 2 think that help understanding synchronized

  • Every object/class have an intrinsic lock associated with it.
  • When a thread invokes a synchronized statement, it automatically acquires the intrinsic lock for that synchronized statement's object and releases it when the method returns. As long as a thread owns an intrinsic lock, NO other thread can acquire the SAME lock => thread safe.

=> When a thread A invokes synchronized(this){// code 1} => all the block code (inside class) where have synchronized(this) and all synchronized normal method (inside class) is locked because SAME lock. It will execute after thread A unlock ("// code 1" finished).

This behavior is similar to synchronized(a variable){// code 1} or synchronized(class).

SAME LOCK => lock (not depend on which method? or which statements?)

Use synchronized method or synchronized statements?

I prefer synchronized statements because it is more extendable. Example, in future, you only need synchronized a part of method. Example, you have 2 synchronized method and it don't have any relevant to each other, however when a thread run a method, it will block the other method (it can prevent by use synchronized(a variable)).

However, apply synchronized method is simple and the code look simple. For some class, there only 1 synchronized method, or all synchronized methods in the class in relevant to each other => we can use synchronized method to make code shorter and easy to understand

Note

(it not relevant to much to synchronized, it is the different between object and class or none-static and static).

  • When you use synchronized or normal method or synchronized(this) or synchronized(non-static variable) it will synchronized base on each object instance.
  • When you use synchronized or static method or synchronized(class) or synchronized(static variable) it will synchronized base on class

Reference

https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Hope it help

查看更多
回忆,回不去的记忆
5楼-- · 2018-12-31 05:45

Synchronized simply means that multiple threads if associated with single object can prevent dirty read and write if synchronized block is used on particular object. To give you more clarity , lets take an example :

class MyRunnable implements Runnable {
    int var = 10;
    @Override
    public void run() {
        call();
    }

    public void call() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                var++;
                System.out.println("Current Thread " + Thread.currentThread().getName() + " var value "+var);
            }
        }
    }
}

public class MutlipleThreadsRunnable {
    public static void main(String[] args) {
        MyRunnable runnable1 = new MyRunnable();
        MyRunnable runnable2 = new MyRunnable();
        Thread t1 = new Thread(runnable1);
        t1.setName("Thread -1");
        Thread t2 = new Thread(runnable2);
        t2.setName("Thread -2");
        Thread t3 = new Thread(runnable1);
        t3.setName("Thread -3");
        t1.start();
        t2.start();
        t3.start();
    }
}

We've created two MyRunnable class objects , runnable1 being shared with thread 1 and thread 3 & runnable2 being shared with thread 2 only. Now when t1 and t3 starts without synchronized being used , PFB output which suggest that both threads 1 and 3 simultaneously affecting var value where for thread 2 , var has its own memory.

Without Synchronized keyword

    Current Thread Thread -1 var value 11
    Current Thread Thread -2 var value 11
    Current Thread Thread -2 var value 12
    Current Thread Thread -2 var value 13
    Current Thread Thread -2 var value 14
    Current Thread Thread -1 var value 12
    Current Thread Thread -3 var value 13
    Current Thread Thread -3 var value 15
    Current Thread Thread -1 var value 14
    Current Thread Thread -1 var value 17
    Current Thread Thread -3 var value 16
    Current Thread Thread -3 var value 18

Using Synchronzied, thread 3 waiting for thread 1 to complete in all scenarios. There are two locks acquired , one on runnable1 shared by thread 1 and thread 3 and another on runnable2 shared by thread 2 only.

Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -1 var value 12
Current Thread Thread -2 var value 12
Current Thread Thread -1 var value 13
Current Thread Thread -2 var value 13
Current Thread Thread -1 var value 14
Current Thread Thread -2 var value 14
Current Thread Thread -3 var value 15
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 17
Current Thread Thread -3 var value 18
查看更多
素衣白纱
6楼-- · 2018-12-31 05:48

What is the synchronized keyword?

Threads communicate primarily by sharing access to fields and the objects reference fields refer to. This form of communication is extremely efficient, but makes two kinds of errors possible: thread interference and memory consistency errors. The tool needed to prevent these errors is synchronization.

Synchronized blocks or methods prevents thread interference and make sure that data is consistent. At any point of time, only one thread can access a synchronized block or method (critical section) by acquiring a lock. Other thread(s) will wait for release of lock to access critical section.

When are methods synchronized?

Methods are synchronized when you add synchronized to method definition or declaration. You can also synchronize a particular block of code with-in a method.

What does it mean pro grammatically and logically?

It means that only one thread can access critical section by acquiring a lock. Unless this thread release this lock, all other thread(s) will have to wait to acquire a lock. They don't have access to enter critical section with out acquiring lock.

This can't be done with a magic. It's programmer responsibility to identify critical section(s) in application and guard it accordingly. Java provides a framework to guard your application, but where and what all sections to be guarded is the responsibility of programmer.

More details from java documentation page

Intrinsic Locks and Synchronization:

Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.

Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them.

A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.

When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquisition of the same lock.

Making methods synchronized has two effects:

First, it is not possible for two invocations of synchronized methods on the same object to interleave.

When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.

Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object.

This guarantees that changes to the state of the object are visible to all threads.

Look for other alternatives to synchronization in :

Avoid synchronized(this) in Java?

查看更多
长期被迫恋爱
7楼-- · 2018-12-31 05:49

Think of it as a kind of turnstile like you might find at a football ground. There are parallel steams of people wanting to get in but at the turnstile they are 'synchronised'. Only one person at a time can get through. All those wanting to get through will do, but they may have to wait until they can go through.

查看更多
登录 后发表回答