About synchronization, asynchrony, multithreading, multithreading synchronization, concurrency in Java

1. Synchronization and Asynchronous

1.1 Synchronization

In a multi-threaded environment, data sharing is often encountered, that is, when multiple threads need to access a resource together, they need to ensure that the resource is only available at a certain time in a certain order. It can be used by one thread, otherwise, the running result of the program will be unpredictable. In this case, the data must be synchronized. For example, multiple threads write the same data at the same time, that is, when thread A needs to use a certain When using a resource, if the resource is being used by thread B, the synchronization mechanism will make thread A wait until thread B finishes using the resource before thread A can use the resource. It can be seen that the synchronization mechanism can guarantee the resource. security.

To achieve synchronization, you must acquire a lock on each thread object. Acquiring it guarantees that only one thread can enter the critical section (block of code accessing the mutex) at a time, and no other threads can enter the critical section until the lock is released. If there are other threads that want to acquire the lock of the object, they can only enter the queue and wait. Only when the thread that owns the object lock exits the critical section, it will be released, and the thread with the highest priority in the waiting queue can obtain the lock and enter the shared code area.

2. Multithreading Methods

for implementing java multithreading

(1) Inheriting the Thread class, rewriting the run() method

Thread is essentially an instance of the Runnable interface, which represents an instance of a thread, and the only way to start a thread is Via the start() method of the Thread class. The start() method is a local method, it will start a new thread and execute the run() method (only the run() method called by the start() method can really play an asynchronous role).
**Tips** After the start() method is called, it does not execute the multithreaded code immediately, but makes the thread runable. When to run the multithreaded code is determined by the operating system. (Ready, Running, Suspended, Ended)

(2) Implement the Runnable interface and implement the run() method.

Tips Create a Thread object and use the object of the previous Runnable interface as a parameter to instantiate and change the Thread object.

Implement the Callable interface and override the call() method. (This is not the point and not recommended)

3. Multi-thread

synchronization What are the methods of multi-thread synchronization?

(1) synchronized keyword

In java, each object has an object lock associated with it, which indicates that the object is only allowed to be owned by one thread at any time. When a thread calls a synchronized code of the object, first To acquire this lock, and then execute the corresponding code, the execution ends, and the lock is released.

There are two main usages of the synchronized keyword:
1.synchronized declaration method: public synchronized void xxx();
2.synchronized code block: synchronized(obj){}

(2) wait() method and notify() method

wait() method Indicates to give up the current ownership of the resource and release the object lock and enter the waiting state until someone notices it.
The notify() method indicates that the current thread has given up possession of the resource, and notifies the waiting thread to obtain the possession of the resource. Then the statement following wait() is run. The awakened thread is still blocked in wait() until the lock of the object is obtained.
Important content: The notify() method gives up the occupation of the resource but does not release the object lock. The

notify() and wait() methods need to be used with the synchronized keyword.

**"`
public class Consumer implements Runnable {

@Override
public synchronized void run() {
        // TODO Auto-generated method stub
        int count = 10;
        while(count > 0) {
             synchronized (Test. obj) {

                 System. out.print( "B");
                 count --;
                 Test. obj.notify(); // 主动释放对象资源

                  try {
                       Test. obj.wait();

                 } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                       e.printStackTrace();
                 }
            }

       }
}
}

public class Produce implements Runnable {

@Override
public void run() {
        // TODO Auto-generated method stub
        int count = 10;
        while(count > 0) {
             synchronized (Test. obj) {

                  //System.out.print("count = " + count);
                 System. out.print( "A");
                 count --;
                 Test. obj.notify();

                  try {
                       Test. obj.wait();
                 } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                       e.printStackTrace();
                 }
            }

       }

}
}

The test class is as follows:

public class Test {

public static final Object obj = new Object();

public static void main(String[] args) {

        new Thread( new Produce()).start();
        new Thread( new Consumer()).start();

}
}
"`**

(3) Lock

a.lock(): acquire the lock in a blocking manner, that is, if the lock is acquired, return immediately; if other threads hold the lock , the current thread waits and returns after knowing the lock is acquired.

b.tryLock(): acquires the lock in a non-blocking way. Just try to acquire the lock, if it is acquired, it returns true, otherwise, it returns false immediately.

c.tryLock(long timeout, TimeUnit unit): If the lock is acquired, it will return true immediately, otherwise it will wait for the time unit given by the parameter. During the waiting process, if the lock is acquired, it will return true immediately, and if the wait times out, it will return false.

d.lockInterruptibly(): If the lock is acquired, return immediately. Otherwise, the current thread sleeps until the lock is acquired, or the current thread is interrupted by another thread. The biggest difference between him and the lock() method is that if the lock() method cannot acquire the lock, it will always be blocked and the interrupt() method will be ignored.

**`In addition to the cooperation of wait() and notify() to achieve thread synchronization, the use of Lock can also achieve the same purpose.

ReentrantLock has the same concurrency and memory semantics as synchronized, and also includes interrupt lock waiting and timing lock waiting, which means that if thread A acquires the lock of object obj first, thread B can still be unable to acquire the lock within the specified time. Then the lock will be automatically relinquished.

However, since synchronized is implemented at the JVM level, the system can monitor whether the lock is released or not. However, ReentrantLock is implemented using code, and the system cannot automatically release the lock. You need to explicitly release the lock in the finally clause in the code lock.unlock() ;

The same example, how to use lock?

public class Consumer implements Runnable {

private Lock lock;
public Consumer(Lock lock) { this.lock
        = lock;
}
@Override
public void run() {
        // TODO Auto-generated method stub
        int count = 10;
        while( count > 0 ) {
             try {
                  lock.lock();
                 count --;
                 System. out.print( "B");
            } finally {
                  lock.unlock(); //主动释放锁
                  try {
                       Thread. sleep(91L);
                 } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                       e.printStackTrace();
                 }
            }
       }

}
}

public class Producer implements Runnable{

private Lock lock;
public Producer(Lock lock) {
        this. lock = lock;
}
@Override
public void run() {
        // TODO Auto-generated method stub
        int count = 10;
        while (count > 0) {
             try {
                  lock.lock();
                 count --;
                 System. out.print( "A");
            } finally {
                  lock.unlock();
                  try {
                       Thread. sleep(90L);
                 } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                       e.printStackTrace();
                 }
            }
       }
}
}

Calling code:

public class Test {

public static void main(String[] args) {
       Lock lock = new ReentrantLock();

       Consumer consumer = new Consumer(lock);
       Producer producer = new Producer(lock);

        new Thread (consumer).start();
        new Thread( producer).start();

}
}

Usage suggestion:

In the case of small concurrency, using synchronized is a good choice, but in the case of high concurrency, its The performance degradation is severe, and ReentrantLock is a good solution at this time. `**

4. Concurrency and Parallelism

Concurrency : A single processor executes multiple tasks in turn, and it seems that multiple tasks are executing at the same time.

Parallel: Multiple processors, executing multiple tasks at the same time, but each task is assigned to execute on one CPU.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326118157&siteId=291194637