Java concurrent programming-graphical interface applications and deadlocks
I don't know why this book will introduce an interface application. The Java interface is very poor and inefficient, and the interface is a weakness of java, it may be because you have some knowledge about concurrent programming.
Why is the GUI single-threaded?
Both Swing and AWT are single-threaded. However, it is not limited to java. In Qt, NexiStep, macOs CoCoa X windows, and other environments, the GUI framework is single-threaded. Many people have tried to write multi-threaded GUI frameworks, but in the end, they all return to the single-thread event queue model due to stability issues caused by race conditions and deadlocks: using a dedicated thread to extract events from the queue, and forward them to the event processor defined by the application.
These problems mainly occur in deadlocks caused by lock sequence problems:
For example, modify the background color of a program:
The order is that the application sends a modification background request-component class-the operating system for rendering.
Then, the operating system draws the component class ---- refreshes the application interface.
On the other hand, we need to ensure that every object is thread-safe, which leads to inconsistent lock sequence and lead to deadlocks.
There are so many interface applications, because I think this utility is not very practical. Knowing the above knowledge can avoid a lot of detours when developing the GUI framework.
Avoid activity risks
Security and activity are relative. We use the locking mechanism to ensure thread security, and it may also cause activity problems due to deadlocks and other reasons.
Deadlock
There is a typical philosopher's dining question used to describe deadlocks.
Five philosophers sat at a table with only five chopsticks on the table. They had to eat with a pair of chopsticks. They sometimes thought, sometimes eat, and when they were thinking, the people next to him can have dinner. The deadlock below is that each of them quickly grabbed the chopsticks on the left and then everyone was waiting for the chopsticks on the right. However, none of them had eaten, so no one will put down the chopsticks, so they are deadlocked. This is a deadlock.
In the design of the database system, the monitoring deadlock and recovery from the deadlock are considered. When a transaction is executed, if a deadlock occurs in a transaction, it will stop the transaction and then execute other transactions. When all other transactions are completed, come back and execute the abandoned transaction again.
However, the JVM does not have this system. When a set of java threads encounter deadlocks, these threads will never be used. Depending on the thread's work, the application may be completely stopped. The only solution is to restart.
Line sequence deadlock
For example, haha thought a lot of ways to lock the lock, that is, to enlarge the acquisition time between two objects.
public class LeftRightDealLock {private final Object right = new Object();private final Object left = new Object();public void leftRight() {synchronized (left) {try {Thread.sleep(500);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}synchronized (right) {dosomething();}}}public void Rightleft() {synchronized (right) {try {Thread.sleep(500);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}synchronized (left) {dosomething();}}}private void dosomething() {// TODO Auto-generated method stubfor (int i = 0; i < 100; i++) {System.out.println("dosomething" + i);}}public static void main(String[] args) {final LeftRightDealLock lrdl = new LeftRightDealLock();new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stublrdl.leftRight();}}).start();new Thread(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stublrdl.Rightleft();}}).start();}}
Dynamic lock sequence deadlock
Take the transfer operation as an Example
public void transferMoney(Account formaccaount, Account toaccount,DollarAmount amount) {synchronized (formaccaount) {synchronized (toaccount) {if (formaccaount.getBalance.compareTo(amount) < 0) {throw new InsufficientFundsExcetion();} else {fromaccount.debit(amount);toaccount.credit(amount);}}}}
It seems that there is no problem. If two people transfer money to each other's account, the above RIghtleftDeadLock will become a problem.
Solution: the lock sequence is used to avoid deadlocks. The bell-ring operator is required. Since it is caused by the lock sequence, a fixed lock sequence can be defined to solve this problem.
public class TestLock {private static final Object tieLock = new Object();private Account fromacct;private Account toacct;public void transferMoney(final Account fromacct, final Account toacct,final DollarAmount amount) {this.fromacct = fromacct;this.toacct = toacct;class Helper {public void transfer() {if (fromacct.getBalance().compareTo(amount) < 0) {throw new InsufficientFundsExcetion();} else {fromacct.debit(amount);toacct.credit(amount);}}}int fromHash = System.identityHashCode(fromacct);int toHash = System.identityHashCode(toacct);if (fromHash < toHash) {synchronized (fromacct) {synchronized (toacct) {new Helper().transfer();}}} else if (fromHash > toHash) {synchronized (toacct) {synchronized (fromacct) {new Helper().transfer();}}} else {synchronized (tieLock) {synchronized (fromacct) {synchronized (toacct) {new Helper().transfer();}}}}}private class DollarAmount {}private abstract class Account {Comparable
getBalance() {return new Comparable
() {@Overridepublic int compareTo(DollarAmount o) {// TODO Auto-generated method stubreturn 0;}};}abstract void debit(DollarAmount a);abstract void credit(DollarAmount a);}}
If it is changed, only the red letter is not displayed in EClipse. However, the exception is not written. Mainly depends on the code,
The System. identityHashCode method is used to obtain the hashcode result in the object. In rare cases, two objects may have the same hash value. Use the overtime lock. Obtain the lock before obtaining the two Account locks. This ensures that only one thread obtains the two locks in an unknown order.