In multithreaded programming for the control of shared variables is very important, the usual program because it is single-threaded to deal with, so there will not be variable resources at the same time by multiple threads to access the changes, the program's operation is sequential. However, in a multi-threaded environment, the resources will be acquired by multiple threads at the same time to make changes in the situation, you can see the following procedure:
public class Mythread implements runnable{
private int i=0;
public void Run () {
try{
i++;
System.out.println (Thread.CurrentThread (). GetId () + ": I is" + i);
Thread.Sleep (1000);
} catch (Exception e) {
System.out.println (e.getmessage ());
}
}
public static void Main (string[] args) {
Executorservice Executorservice = Executors.newfixedthreadpool (3);
Mythread thread = new Mythread ();
for (int i=0; i<6; i++) {
executorservice.submit (thread);}}}
One of the possible results shown after running this program is as follows:
The three threads generated by the thread pool with IDs of 10,11,12 begin to work, at the first time at the same time to get I and the self-add operation, and finally print output, so I showed the value of 3, followed by three threads are successively get I and make changes, so the output is 4,5,6.
If you want to access the shared resource variable I in a sequential manner, you need to add a lock, then the first thought is to use synchronized to control the lock.
Public synchronized void Run () {
try{
i++;
System.out.println (Thread.CurrentThread (). GetId () + ": I is" + i);
Thread.Sleep (1000);
} catch (Exception e) {
System.out.println (e.getmessage ());
}
}
Lock execution results after:
I can see from the results that I was in order plus 1.
Another way is to use a reentrant lock
public class Threadwithreentrantlock implements runnable{public
static Reentrantlock lock = new Reentrantlock ();
private int i=0;
public void Run () {
try{
lock.lock ();
i++;
System.out.println (Thread.CurrentThread (). GetId () + ": I is" + i);
Thread.Sleep (1000);
} catch (Exception e) {
System.out.println (e.getmessage ());
} finally {
lock.unlock ();
}} public static void Main (string[] args) {
Executorservice Executorservice = Executors.newfixedthreadpool (3);
Threadwithreentrantlock thread = new Threadwithreentrantlock ();
for (int i=0; i<6; i++) {
executorservice.submit (thread);}}}
Run Result:
Whether a keyword sychronized or a reentrant lock will not cause a deadlock, sychronized will have a default counter to implement the lock release, and the reentrant lock will be unlocked in the finaiily code block. What is the benefit of a reentrant lock, see the example below.
public class Threadwithreentrantlock implements Runnable {public static Reentrantlock lock = new Reentrantlock ();
private int i=0;
public void Run () {System.out.println (Thread.CurrentThread (). GetId () + ": Begin ..."); try{if (Lock.trylock ()) {System.out.println (Thread.CurrentThread (). GetId () + ": ge
T lock successfully ... ");
else {System.out.println (Thread.CurrentThread (). GetId () + ": Get Lock failed ...");
Lock.lockinterruptibly ();
} lock.lock ();
i++;
System.out.println (Thread.CurrentThread (). GetId () + ": I is" + i);
Thread.Sleep (3000);
catch (Exception e) {System.out.println (E.getmessage ());
finally {Lock.unlock (); } public static void Main (string[] args) {Executorservice exEcutorservice = Executors.newfixedthreadpool (3);
Threadwithreentrantlock thread = new Threadwithreentrantlock ();
for (int i=0; i<6; i++) {executorservice.submit (thread); }
}
}
Run Result:
You can see that thread 111 holds the lock, while 12 and 10 are trying to acquire the lock because the thread 11 holds the lock because it is in concurrency, so they take a break and let them out of the lock, ensuring that the program continues.
It can be concluded that the place where the sychronized is better than the other is to find out if the lock is occupied and can interrupt control. As you can see, sychronized is a synchronization keyword provided by the JDK, but it also implements the lock work
Can, the essence of sychronized is a built-in lock, is the JVM for concurrent objects set built-in lock, to ensure concurrency, however, the drawbacks of the built-in lock is not visible, can not be controlled. In development, it is recommended to use a heavy
Into the lock, to be able to display the control.