The difference between two implementations of Java multithreading and the lock object in the deep synchronization problem

Source: Internet
Author: User

First of all we know that there are two ways to create a thread:

1. Inherit the Thread class;2. Implement Runnable interface.

But these two are not exactly the same. Here's a talk about the difference:

Because Java does not support multiple inheritance (interfaces can inherit multiple interfaces.) But generally we do not mention), but support multiple implementations. When a class inherits from the parent class, it can no longer inherit the thread class and can only create threads by implementing an interface.

Inheriting the Runnable interface is more consistent with object-oriented thinking. The thread is divided into two parts, one is the thread object and the other is the thread task. Inherits the thread class, which is coupled with the threading object and the thread task ( code within the Run method). Once the child class object of the thread class is created, both the thread object and the thread task. The implementation of the Runnable interface is to separate the thread task into an object, and the type is the Runnable interface type. The thread task is determined by the parameters passed. the runable interface decouples The thread object from the thread task.

The third difference is that when you write a sync function, there are obvious differences between the two ways.

In general, we generally use the form of implementing interfaces to create threads.

Here's a question about the sync lock.

Java 's problem with synchronization has two ways of writing, one is code block write synchronization, but write synchronous function. There is a difference between the two.

The lock used by the synchronization function is a fixed this(that is , the object that implements the class of the Runnable interface), when the thread task only needs a synchronization, it can be fully reflected by the synchronous function;

The lock for the synchronization code block uses any object and must be distinguished by a lock when the thread task requires more synchronization.

Here's a detailed explanation: First look at a deadlock example program:

/* Idea: Deadlock, nesting synchronization is the simplest. * Two lock objects are nested. Two threads perform the same two lock object nesting */class MyLock {public static final object Locka = new Object ();p ublic static Final Object lockb = new Ob Ject ();} Class Test implements Runnable {private Boolean flag; Test (Boolean flag) {This.flag = flag;} public void Run () {if (flag) {while (true) {synchronized (Mylock.locka) {System.out.println (Thread.CurrentThread ()). GetName () + "... if ..... Locka "), synchronized (mylock.lockb) {System.out.println (Thread.CurrentThread (). GetName () +" ..... Lockb ");}}} else {while (true) {synchronized (mylock.lockb) {System.out.println (Thread.CurrentThread (). GetName () + "... else ... Lockb "); synchronized (Mylock.locka) {System.out.println (Thread.CurrentThread (). GetName () +" ... else ..... Locka ");}}}}} public class DeadLock {public static void main (string[] args) {Test test1 = new Test (true); Test test2 = new test (false); thread T1 = new Thread (test1); Thread t2 = new Thread (test2); T1.start (); T2.start ();}}

where Mylocka and mylockb refer to different object objects, but can also be objects of other classes, because object locks can be arbitrary objects

But if it is written in the form of a synchronous function, then the lock object is a fixed this, and we also know that this is always pointing to the current object (that is, who called this function, this who is referring to. So when Implementing Multi-threading with the inherited thread class, it is not possible to achieve synchronization because different threads are different thread subclass Objects . This refers to the same, so the lock is not the same. The following is a procedural proof of opinion:

Class Bank {private int sum;public void add (int num) {sum + = num; System.out.println (Thread.CurrentThread (). GetName () + "... sum=" + sum);}} Class Customer extends thread{private Bank B = new Bank (), @Overridepublic Void Run () {this.storage ();} Public synchronized void Storage () {for (int i = 0; i < 5; i++) {if (i = = 3) try {thread.sleep (n);} catch (Interrupte Dexception e) {//TODO auto-generated catch Blocke.printstacktrace ();} B.add (100);}} public class Bankandcustomer {public static void main (string[] args) {Customer C1 = new Customer (); Customer C2 = new Customer (); C1.start (); C2.start ();}}

The output of the above code is (of course, the output result of multi-threaded is not unique):


Where sleep method is not a lock object, But when one of the threads sleeps, the other thread immediately gets the cpu execution, to execute the storage method, This is enough to justify this view.

But by implementing runnable interface in the form of multi-threading, the above problem can be avoided because we are passing runnable interface, two threads are called by the subclass object run method (Recommended view api thread run method, a probe. ), so this The object of the reference is consistent, So when a thread outputs three cycles, hibernation is not interrupted for two seconds, but resumes after waking. The following code is given:

Class Bank {private int sum;public void add (int num) {sum + = num; System.out.println (Thread.CurrentThread (). GetName () + "... sum=" + sum);}} Class Customer implements runnable{private Bank B = new Bank (), @Overridepublic Void Run () {this.storage ();} Public synchronized void Storage () {for (int i = 0; i < 5; i++) {if (i = = 3) try {thread.sleep (n);} catch (Interrupte Dexception e) {//TODO auto-generated catch Blocke.printstacktrace ();} B.add (100);}} public class Bankandcustomer {public static void main (string[] args) {Customer c = new Customer (); thread T1 = new Thread (c); Thread t2 = new Thread (c); T1.start (); T2.start ();}}


At the same time, we need to note that when the synchronization function is labeled as a static function, his default lock object is not this, because there is no this in the static . Called directly by the class name without requiring an object. The lock object becomes the class name . Class, if declared as public static synchronized void in the above example Storage () lock object is Customer.class








The difference between two implementations of Java multithreading and the lock object in the deep synchronization problem

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.