使用synchronized对多个线程的对象进行顺序访问

时间:2016-07-08 12:12:02

标签: java multithreading

我有一个练习,我必须增加一个计数器,对计数器进行平方,然后等待500毫秒再重复操作。 我被迫使用两个线程类和synchronized修饰符。 这是可能的?有人能帮我吗? 这是我的代码:

import static java.lang.Thread.sleep;   

public class Sync2Thread{

     private static Counter c;

     static class Counter{
         private int count;  

         public synchronized int getCount() { 
             return count;
         }

         public synchronized void incrCount() { 
             count++; 
             System.out.println("+1 => counter= "+count);
             try {
                 sleep(500);
             } catch (InterruptedException ex) { 
             }
         }
     }

     public static void main (String[] args){
         c = new Counter();

         Thread t = new Thread(new IncrCounter());
         t.start(); 
         Thread t2 = new Thread(new Square());        
         t2.start();
     }

     /**
       * Thread that increment the counter
       */
     static  class IncrCounter extends Thread {

          public void run(){
             for(int i = 0; i < 7; i++)
             {  
                 System.out.println("Current Counter = "+c.getCount());
                 c.incrCount();  
             }
         }
     }

      /**
       * Thread that calculates the square
       */
     static class Square extends Thread {

         public void run(){
             for(int i = 0; i < 7; i++)
             {   
                 int x = c.getCount();
                 System.out.println(x + " squared =>"+ x*x + "\n");    
                 yield();
             }
         } 
     } 

 }

我的结果类似于:

Current Counter= 0
+1 => counter= 1
Current Counter= 1
+1 =>  counter= 2
1 squared =>1 
2 squared =>4 
2 squared =>4 
2 squared =>4 
2 squared =>4 
.....

但必须是:

Current Counter= 0
+1 => counter= 1
1 squared =>1

Current Counter= 1
+1 => counter= 2
2 squared =>4

Current Counter= 2
+1 => 3
3 squared =>9

非常感谢你

3 个答案:

答案 0 :(得分:0)

我认为主要问题在于yield()方法。它只说“嘿,我已经完成了我的工作。如果其他一些线程需要,它现在可以进入运行状态。”因此它将线程置于可运行状态,然后查看哪些线程处于可运行状态并且可以进入运行状态。如果yield()之前的两行比另一个线程正在等待的500ms快,则square-thread将是唯一处于runnable状态的行。所以它会立即重新开始工作。

解决方案可能是让两个线程使用wait()和notify()等待彼此,或者使用sleep而不是yield。

答案 1 :(得分:0)

很少有建议:

删除synchronizaed方法并使用AtomicInteger代替int count

  

可以原子方式更新的int值。有关原子变量属性的描述,请参阅java.util.concurrent.atomic包规范。 AtomicInteger用于诸如原子递增计数器之类的应用程序

除非在同一个线程中增加和平方或者为这两个线程使用两个不同的Counter实例,否则无法使用当前代码实现预期结果。

示例代码:(由于不同线程中的计数器访问,仍然存在副作用)

import static java.lang.Thread.sleep; 
import java.util.concurrent.atomic.AtomicInteger;
public class Sync2Thread{
     private static Counter c;
     static class Counter{
         private static AtomicInteger count = new AtomicInteger(0);  
         public int getCount() { 
             return count.get();
         }
         public  void incrCount() { 
             count.incrementAndGet();
             System.out.println("+1 => counter= "+getCount());
             try {
                 sleep(500);
             } catch (InterruptedException ex) { 
             }
         }
     }
     public static void main (String[] args){
         c = new Counter();
         Thread t = new Thread(new IncrCounter());
         t.start(); 
         Thread t2 = new Thread(new Square());        
         t2.start();
     }

     /**
       * Thread that increment the counter
       */
     static  class IncrCounter extends Thread {
          public void run(){
             for(int i = 0; i < 7; i++)
             {  
                 System.out.println("Current Counter = "+c.getCount());
                 c.incrCount();  
             }
         }
     }
      /**
       * Thread that calculates the square
       */
     static class Square extends Thread {
         public void run(){
             for(int i = 0; i < 7; i++)
             {   
                 int x = c.getCount();
                 System.out.println(x + " squared =>"+ x*x + "\n");  
                 c.incrCount();  

             }
         } 
     } 
 }

输出:

Current Counter = 0
0 squared =>0

+1 => counter= 1
+1 => counter= 2
Current Counter = 2
+1 => counter= 3
3 squared =>9

+1 => counter= 4
Current Counter = 4
+1 => counter= 5
5 squared =>25

+1 => counter= 6
Current Counter = 6
6 squared =>36

+1 => counter= 7
+1 => counter= 8
8 squared =>64

Current Counter = 8
+1 => counter= 9
+1 => counter= 10
10 squared =>100

+1 => counter= 11
Current Counter = 10
+1 => counter= 12
Current Counter = 12
+1 => counter= 13
13 squared =>169

+1 => counter= 14

答案 2 :(得分:0)

正如用户Doubi所说,它适用于方法wait()和notify()。

$(document).on("click", "#select-files-upload-button", function() {
  $('#select-photos').show();
});

}

输出示例:

import static java.lang.Thread.sleep; 

public class Sync2Thread{

 private static Counter c;

 static class Counter{
     private int count;  

     public int getCount() { 
         return count;
     }

     public void incrCount() { 
         count++; 
         System.out.println("+1 => counter= "+count); 
     }
 }

 public static void main (String[] args){
     c = new Counter();

     Thread t = new Thread(new IncrCounter());
     t.start(); 
     Thread t2 = new Thread(new Square());        
     t2.start();
 }

 /**
   * Thread that increment the counter
   */
 static  class IncrCounter extends Thread {

      public void run(){
         for(int i = 0; i < 5; i++)
         {  
            synchronized (c) {

                try {
                    System.out.println("Thread1 - Current Counter = "+c.getCount());
                    System.out.println("Thread1 - Waiting to get notified after squared");
                    // This waits for the other thread perform exponentiation
                    c.wait();
                } catch (InterruptedException ex) {  }
                System.out.println("Thread1 - Waiter thread got notified, let's raise!"); 
                // As soon as the other thread has raised to a power, it increments the counter.
                c.incrCount(); 
                c.notifyAll();
            }  
         }
         System.out.println("Thread1 end___");
     }
 }

  /**
   * Thread that calculates the square
   */
 static class Square extends Thread {

     public void run(){
         for(int i = 0; i < 5; i++)
         {  
            synchronized (c) {

                int x = c.getCount();
                System.out.println("Thread2 - "+ x + " squared =>"+ x*x);    
                try {
                    sleep(500);
                    System.out.println("Thread2 - Sqared done, send notify\n");
                    c.notifyAll();
                    c.wait();
                } catch (InterruptedException ex) {   }
            }
         }
         System.out.println("Thread2 end___");
     } 
 }