java Multithread sharing data, thread synchronization and mutual exclusion

Keywords: REST Java Eclipse

Written in front

In this paper, taking the ticketing system as an example, two ways of sharing data among java multithreads, thread synchronization, are introduced. There may be many deficiencies in the article. Please understand and welcome comments from the big guys.

What this article uses

  1. java
  2. eclipse 2019-11

Article directory

1. Multi thread data sharing

1.1 shared Runnable

                        .
   here we take the ticketing system with multiple ticket offices as an example. Each ticket office has one thread, and multiple threads share the remaining ticket variables.

class TicketRunnable implements Runnable{
	private int num;
	
	public TicketRunnable(int num) {
		this.num=num;
	}
	@Override
	public void run() {
		for(int i=0;i<5;i++) {	//5 tickets for sale
			if(num>0) {
				num--;
				System.out.println(Thread.currentThread().getName()+":One ticket for sale, the rest"+num);
			}else {
				System.out.println(Thread.currentThread().getName()+":No tickets left");
			}
		}
	}
}
public class Multithreading data sharing {
	public static void main(String[] args) {
		Runnable runnable = new TicketRunnable(8);	//Initialize 8 remaining tickets
		new Thread(runnable,"Wuhan ticket office").start();
		new Thread(runnable,"Beijing ticket office").start();
	}
}

1.2 encapsulating data as objects

   when multiple threads perform the same operation, the method of sharing the Runnable object can be used to share variables. This method is not applicable when different operations are performed. The shared data can be encapsulated as an object, and multiple threads can share the object.
                    .

class Ticket{
	private int num;
	public Ticket(int num) {
		this.num=num;
	}
	public void sell() {
		if(num>0) {
			num--;
			System.out.println(Thread.currentThread().getName()+":One ticket for sale, the rest"+num);
		}else {
			System.out.println(Thread.currentThread().getName()+":No tickets left");
		}
	}
	public void returned() {
		num++;
		System.out.println(Thread.currentThread().getName()+":1 ticket refunded, the rest"+num);
	}
}
public class Multithreading data sharing {
	public static void main(String[] args) {
		Ticket ticket = new Ticket(8);	//Initialize to 8 tickets
		new Thread(new Runnable() {
			@Override
			public void run() {
				for(int i=0;i<8;i++) {
					ticket.sell();//Sell ticket
				}
			}
		},"Ticket Office").start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				for(int i=0;i<8;i++) {
					ticket.returned();//To refund a ticket
				}
			}
		},"Ticket Refund").start();
	}
}

2. Thread synchronization and mutual exclusion

2.1 problems in the above codes

Take the method of sharing Runnable objects to realize synchronization as an example, run the program, and the results are as follows:

Wuhan ticket office: 1 ticket, the remaining 6 tickets
 Wuhan ticket office: 1 ticket, 5 tickets remaining
 Beijing ticket office: 1 ticket, 6 tickets remaining
 Wuhan ticket office: 1 ticket, 4 tickets remaining
 Wuhan ticket office: 1 ticket, remaining 2
 Beijing ticket office: 1 ticket, 3 tickets remaining
 Beijing ticket office: 1 ticket, the remaining 0
 Beijing ticket office: no tickets left
 Beijing ticket office: no tickets left
 Wuhan ticket office: 1 ticket, 1 remaining ticket

                       . The reason for this problem is that when Wuhan ticket office reduces the number of tickets by 1, and the Beijing ticket office also reduces the number of tickets by 1, the output result is 6. It is not output by decrement, but also because the read data has not been output, and another thread has executed the ticket selling output. Slightly modify the run() method of TicketRunnable to

	@Override
	public void run() {
		for(int i=0;i<5;i++) {	//5 tickets for sale
			synchronized (this) {
				if(num>0) {
					num--;
					System.out.println(Thread.currentThread().getName()+":One ticket for sale, the rest"+num);
				}else {
					System.out.println(Thread.currentThread().getName()+":No tickets left");
				}
			}
		}
	}

At this time, the content of the program is output in descending order. Because synchronized adds a synchronization lock to the code block and synchronizes the operation of modifying the value and value, there will be no disorder and incorrect output of remaining tickets.

2.2 synchronization and mutual exclusion

1. What is mutual exclusion?
Many resources in the computer are limited, which is called critical resources. Multiple processes scramble for the same critical resource, and they can run when they get it, but they can't run when they don't get it. Mutual exclusion is the indirect restriction of competing for critical resources. For example, when multiple print threads compete for a printer resource, mutual exclusion is formed between processes.

2. What is synchronization?
Synchronization is to coordinate multiple interrelated threads to complete tasks. There are certain constraints between them, and the execution order is often orderly. Synchronization is a direct constraint relationship between processes, such as supply and marketing system. When the warehouse is full and needs to stop supply, the warehouse is empty and cannot be shipped, then the supply process and the sales process form a synchronization relationship.

2.3 synchronized

synchronized can be used to decorate methods, static methods, and code blocks

//Object locks, decorating methods
synchronized void a() {

}
//Class lock, modifying static methods
synchronized static void b() {

}
void c() {
	//Object lock, decorating code block
	synchronized (this) {
			
	}
	//Class lock, decorated code block
	synchronized (Ticket.class) {

	}	
}

2.4 ReentrantLock for synchronization

1. use

ReentrantLock lock = new ReentrantLock();
lock.lock();	//Lock up
lock.unlock();	//Unlock

2. Realize the above ticket sales synchronization

class TicketRunnable implements Runnable{
	private int num;
	ReentrantLock lock = new ReentrantLock();
	
	public TicketRunnable(int num) {
		this.num=num;
	}
	@Override
	public void run() {
		for(int i=0;i<5;i++) {	//5 tickets for sale
			lock.lock();
			if(num>0) {
				num--;
				System.out.println(Thread.currentThread().getName()+":One ticket for sale, the rest"+num);
			}else {
				System.out.println(Thread.currentThread().getName()+":No tickets left");
			}
			lock.unlock();
		}
	}
}
public class Multithreading data sharing {
	public static void main(String[] args) {
		Runnable runnable = new TicketRunnable(8);	//Initialize 8 remaining tickets
		new Thread(runnable,"Wuhan ticket office").start();
		new Thread(runnable,"Beijing ticket office").start();
	}
}

3. summary

It's hard to understand whether synchronized implements synchronization or mutual exclusion. It's also said on the Internet that synchronized is mutually exclusive. Synchronized implements modified content synchronization. If you don't know clearly, please comment and leave a message. I will reply to everything I see. At the end of this article, please point out any shortcomings.

Published 41 original articles, won praise 21, visited 7859
Private letter follow

Posted by fatal on Mon, 20 Jan 2020 23:50:01 -0800