201871010111- Liu Jiahua "object-oriented programming (java)" Week 17 learning summarize some understanding of synchronized (this) is

201871010111- Liu Jiahua "object-oriented programming (java)" Week 17 learning summary

Experimental seventeen thread synchronization control 

Experimental time 2019 -12-20

Part I: theoretical knowledge summary

16.Java thread scheduling uses priority policies:

    The first implementation of high-priority, low priority after execution;

    Multi-threaded system will automatically assign a priority, by default, inherit its parent priority for each thread;

    Mission-critical threads, the higher the priority; the same priority thread queue according to the principle "first in first out" of.

Call setPriority (int a) reset the priority of the current thread , a value can be static three aforementioned amount.

Call getPriority () to get the current thread priority.

Multi-threaded run concurrently uncertainties solution: the introduction of thread synchronization mechanism, so that another thread To use this method, you can only wait.

The solution multi-thread synchronization in Java, there are two: Java SE 5.0 introduced ReentrantLock class. Added before class methods shared memory synchronized modifier.

The basic structure of the protective ReentrantLock code block with the following:

myLock.lock();

try {

     critical section

}

finally

{

     myLock.unlock(); 

}

 

The key points about the lock object and condition object:

1. The key used to protect code fragment, to ensure that any time only one thread is executing code in protected.

2. Thread the lock manager tried to enter the protected code segment.

3. The lock may have one or more conditions related objects.

4. Each condition object management thread that has entered the protected code segment but can not run.

synchronized keyword role: within a class method with the synchronized modification, the method is called synchronization method; as long as a thread is accessing the synchronization method, other threads want to access the synchronization method will be blocked until the thread returns from before synchronization method wake thread is blocked, other threads parties may enter synchronization method.

In the method of synchronization used wait (), notify and notifyAll () method :

When a thread synchronization method used, it may be necessary problem, you must use the wait () method to make this thread to wait temporarily give up the right to use the CPU, and allow other threads to use this synchronization method.

If you run out of thread synchronization method should be executed notifyAll () method notifies all synchronization due to the use of this method in the waiting thread waiting for the end.

Part II: Experimental part

1, experimental purposes and requirements

(1) Grasp the concept and implementation of thread synchronization technology;

(2) comprehensive programming practice thread

2, experimental and step

Experiment 1: Test procedures and code comments.

Test Procedure 1:

l 651 program debugging textbooks 14-7 in Elipse environment, combined result of the program understand the program;

l mastered the use of multithreading synchronization lock objects and conditions for realization of the object.

. 1  Package Synch;
 2  
. 3  Import Classes in java.util *. ;
 . 4  Import in java.util.concurrent.locks *. ;
 . 5  
. 6  / ** 
. 7  . A Bank with A * Number of Bank Accounts that uses Locks for serializing Access
 . 8  * @ Version 1.30 2004-08-01
 . 9  * @author Cay Horstmann
 10   * / 
. 11  public  class Bank
 12 is  {
 13 is     Private  Final  Double [] Accounts;
 14     / ** synchronous control object related class * /
15    private Lock bankLock;           //lock对象
16    private Condition sufficientFunds;//condition对象   
17 
18    /**
19     * Constructs the bank.
20     * @param n the number of accounts
21     * @param initialBalance the initial balance for each account
22     */
23    public Bank(int n, double initialBalance)
24    {
25       accounts = new double[n];
26       Arrays.fill(accounts, initialBalance); //数组account的填充
27       bankLock = new ReentrantLock();
28       sufficientFunds = bankLock.newCondition();
29    }
30 
31    /**
32     * Transfers money from one account to another.
33     * @param from the account to transfer from
34     * @param to the account to transfer to
35     * @param amount the amount to transfer
36     */
37    public void transfer(int from, int to, double amount) throws InterruptedException //模拟行内转账操作
38    {
39       bankLock.lock(); //加锁操作
40       try
41       {
42          while (accounts[from] < amount)
43             sufficientFunds.await();         //阻塞事件队列
44          System.out.print(Thread.currentThread());
45          accounts[from] -= amount;
46          System.out.printf(" %10.2f from %d to %d", amount, from, to);
47          Accounts [to] + = AMOUNT;
 48           System.out.printf ( "the Total Balance:% n-% 10.2f" , getTotalBalance ());
 49           sufficientFunds.signalAll (); // wake up all the threads 
50        }
 51 is        the finally 
52 is        {
 53 is           bankLock.unlock (); // unlock operation 
54 is        }
 55     }
 56 is  
57 is     / ** 
58      * Gets, Account Balances The SUM of All.
 59      * @return The Balance Total
 60      * / 
61 is     public  Double getTotalBalance()
62    {
63       bankLock.lock();
64       try
65       {
66          double sum = 0;
67 
68          for (double a : accounts)
69             sum += a;
70 
71          return sum;
72       }
73       finally
74       {
75          bankLock.unlock();
76       }
77    }
78 
79    /**
80     * Gets the number of accounts in the bank.
81     * @return the number of accounts
82     */
83    public int size()
84    {
85       return accounts.length;
86    }
87 }

 

package synch;

/**
 * This program shows how multiple threads can safely access a data structure.
 * @version 1.31 2015-06-21
 * @author Cay Horstmann
 */
public class SynchBankTest
{
   public static final int NACCOUNTS = 100;
   public static final double INITIAL_BALANCE = 1000;
   public static final double MAX_AMOUNT = 1000;
   public static final int DELAY = 10;
   
   public static void main(String[] args)
   {
      Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);
      for (int i = 0; i < NACCOUNTS; i++)
      {
         int fromAccount = i;
         Runnable r = () -> {
            try
            {
               while (true)
               {
                  int toAccount = (int) (bank.size() * Math.random());
                  double amount = MAX_AMOUNT * Math.random();
                  bank.transfer (fromAccount, toAccount, AMOUNT); 
                  the Thread.sleep (( int ) (Math.random the DELAY * ())); // randomly generated time to the executing thread to sleep 
               } 
            } 
            the catch (InterruptedException E) 
            { 
            }             
         }; 
         the Thread T = new new the Thread (R & lt); 
         t.start (); 
      } 
   } 
}

 

Run shot:

 

 

 

Test Procedure 2:

l 655 program debugging textbooks 14-8 in Elipse environment, combined result of the program understand the program;

Application synchronized in a multithreaded synchronization of l grasp.

package synch2;

import java.util.*;

/**
 * A bank with a number of bank accounts that uses synchronization primitives.
 * @version 1.30 2004-08-01
 * @author Cay Horstmann
 */
public class Bank
{
   private final double[] accounts;

   /**
    * Constructs the bank.
    * @param n the number of accounts
    * @param initialBalance the initial balance for each account
    */
   public Bank(int n, double initialBalance)
   {
      accounts = new double[n];
      Arrays.fill(accounts, initialBalance);
   }

   /**
    * Transfers money from one account to another.
    * @param from the account to transfer from
    * @param to the account to transfer to
    * @param amount the amount to transfer
    */
   public synchronized void transfer(int from, int to, double amount) throws InterruptedException//sysynchronized implemented method modifying keywords locking operation 
   {
       the while (Accounts [from] < AMOUNT) 
         the wait ();   // the wait () method causes the thread enters a wait state until it is notified, the method can only be called a synchronization method of the 
      System .out.print (Thread.currentThread ()); // Thread.currentThread () returns the current execution thread thread object 
      Accounts [from] - = AMOUNT; 
      System.out.printf ( "% 10.2f% from D to D% " , AMOUNT, from, to); 
      Accounts [to] + = AMOUNT; 
      System.out.printf ( " the Total Balance:% n-% 10.2f " , getTotalBalance ()); 
      notifyAll (); // releasing the object at those blocked on the call to the thread wait 
   } 

   / **
    * Gets the sum of all account balances.
    * @return the total balance
    */
   public synchronized double getTotalBalance()
   {
      double sum = 0;

      for (double a : accounts)
         sum += a;

      return sum;
   }

   /**
    * Gets the number of accounts in the bank.
    * @return the number of accounts
    */
   public int size()
   {
      return accounts.length;
   }
}

 

package synch2;

/**
 * This program shows how multiple threads can safely access a data structure,
 * using synchronized methods.
 * @version 1.31 2015-06-21
 * @author Cay Horstmann
 */
public class SynchBankTest2
{
   public static final int NACCOUNTS = 100;
   public static final double INITIAL_BALANCE = 1000;
   public static final double MAX_AMOUNT = 1000;
   public static final int DELAY = 10;

   public static void main(String[] args)
   {
      Bank bank = new Bank(NACCOUNTS, INITIAL_BALANCE);
      for (int i = 0; i < NACCOUNTS; i++)
      {
         int fromAccount = i;
         /**lamber表达式*/
         /*Runnable r = () -> {
            try
            {
               while (true)
               {
                  int toAccount = (int) (bank.size() * Math.random());
                  double amount = MAX_AMOUNT * Math.random();
                  bank.transfer(fromAccount, toAccount, amount);
                  Thread.sleep((int) (DELAY * Math.random()));
               }
            }
            catch (InterruptedException e)
            {
            }
         };*/
        /**直接声明
         *  Runnable r=new Runnable() {
            
            @Override
            public void run() {
                try
                {
                   while (true)
                   {
                      int toAccount = (int) (bank.size() * Math.random());
                      double amount = MAX_AMOUNT * Math.random();
                      bank.transfer(fromAccount, toAccount, amount);
                      Thread.sleep((int) (DELAY * Math.random()));
                   }
                }
                catch (InterruptedException e)
                {
                }
             };
                
            
        };*/
         
         /**
                                  *  匿名内部类
                      */
         Thread t = new Thread(new Runnable(){
             
             @Override
             public void run() {
                 try
                 {
                    while (true)
                    {
                       int toAccount = (int) (bank.size() * Math.random());
                       double amount = MAX_AMOUNT * Math.random();
                       bank.transfer(fromAccount, toAccount, amount);
                       Thread.sleep((int) (DELAY * Math.random()));
                    }
                 }
                 catch (InterruptedException e)
                 {
                 }
              };
                 
             
         });
         t.start();
      }
   }
}

 

operation result:

 

 

 

Test Procedure 3:

l Elipse run the following program in the environment, in conjunction with the results of analysis program running problems;

l try to resolve program problems.

class Cbank

{

     private static int s=2000;

     public   static void sub(int m)

     {

           int temp=s;

           temp=temp-m;

          try {

     Thread.sleep((int)(1000*Math.random()));

   }

           catch (InterruptedException e)  {              }

          s=temp;

          System.out.println("s="+s);

  }

}

 

 

class Customer extends Thread

{

  public void run()

  {

   for( int i=1; i<=4; i++)

     Cbank.sub(100);

    }

 }

public class Thread3

{

 public static void main(String args[])

  {

   Customer customer1 = new Customer();

   Customer customer2 = new Customer();

   customer1.start();

   customer2.start();

  }

}

源代码运行截图:

 

 

 会发现源代码运行结果错误;这是由于多线程并发执行过程(两个或者两个以上的线程共享某个对象,每一个对象都调用该对象的状态方法)中存在问题

1.多线程的相对执行顺序不确定

2.执行顺序的不确定会产生执行结果的不确定性

3.在多线程对于共享数据的操作时常常会产生不确定性

修改后代码(采用关键字synchronized修饰方法修改程序)

package op;

class Cbank
{
     private static int s=2000;
     public  synchronized static void sub(int m)
     {
           int temp=s;
           temp=temp-m;
          try {
                 Thread.sleep((int)(1000*Math.random()));
               }
           catch (InterruptedException e)  {              }
              s=temp;
              System.out.println("s="+s);
          }
    }


class Customer extends Thread
{
  public void run()
  {
   for( int i=1; i<=4; i++)
     Cbank.sub(100);
    }
 }
public class Thread3
{
 public static void main(String args[])
  {
   Customer customer1 = new Customer();
   Customer customer2 = new Customer();
   customer1.start();
   customer2.start();
  }
}

 

运行截图:

 

 

实验2 编程练习

利用多线程及同步方法,编写一个程序模拟火车票售票系统,共3个窗口,卖10张票,程序输出结果类似(程序输出不唯一,可以是其他类似结果)。

Thread-0窗口售:第1张票

Thread-0窗口售:第2张票

Thread-1窗口售:第3张票

Thread-2窗口售:第4张票

Thread-2窗口售:第5张票

Thread-1窗口售:第6张票

Thread-0窗口售:第7张票

Thread-2窗口售:第8张票

Thread-1窗口售:第9张票

Thread-0窗口售:第10张票

  1.设计思路:出票时三个窗口并行造作,可抽象为三个线程并行占用cpu,可以利用关键字synchronized使得实现并发操作。

 2.对synchronized(this)的一些理解

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用.

   3.整体实验代码

package TeamWork06;

class Ticketsthread implements Runnable {
    public static final int DELAY = 1000;
    int t = 1;
    boolean flag = true;

    public void run() {
        while (flag) {
            try {
                Thread.sleep((int) (DELAY * Math.random()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (this) {
                if (t <= 10) {
                    System.out.println(Thread.currentThread().getName() + "窗口售:第" + t + "張票");
                    t++;
                }
                if (t > 10) {
                    flag = false;
                }
            }
        }

    }
}

public class TicketsTest {
    public static void main(String[] args) {
        Ticketsthread th = new Ticketsthread();
         new Thread(th).start();
         new Thread(th).start();
         new Thread(th).start();
        
    }
}

 

运行截图:

 

 

 

第三部分:实验心得

   通过本周的学习,了解到了解决多线程同步问题的两种方法:ReentrantLock类和synchronized修饰符,理解了其使用方法,能够使用简单的编程实现方法的使用来处理并发问题.在实验课上收获了当注释调代码sufficientFunds.await();会出现死锁状态等知识,感受颇多。注意点有:线程如果用完同步方法,应当执行notifyAll()方 法通知所有由于使用这个同步方法而处于等待的 线程结束等待。线程如果用完同步方法,应当执行notifyAll()方 法通知所有由于使用这个同步方法而处于等待的 线程结束等待。以后会坚持学习Java。

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用.

   3.整体实验代码

package TeamWork06;

class Ticketsthread implements Runnable {
    public static final int DELAY = 1000;
    int t = 1;
    boolean flag = true;

    public void run() {
        while (flag) {
            try {
                Thread.sleep((int) (DELAY * Math.random()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (this) {
                if (t <= 10) {
                    System.out.println(Thread.currentThread().getName() + "窗口售:第" + t + "張票");
                    t++;
                }
                if (t > 10) {
                    flag = false;
                }
            }
        }

    }
}

public class TicketsTest {
    public static void main(String[] args) {
        Ticketsthread th = new Ticketsthread();
         new Thread(th).start();
         new Thread(th).start();
         new Thread(th).start();
        
    }
}

 

运行截图:

 

 

 

Guess you like

Origin www.cnblogs.com/JerryLau-213/p/12072261.html