Java中利用synchronized关键字实现多线程同步问题 .


    Java 中多线程的同步依靠的是对象锁机制,synchronized关键字就是利用了封装对象锁来实现对共享资源的互斥访问。
      下面以一个简单例子来说明多线程同步问题,我们希望在run()方法里加入synchronized关键字来实现互斥访问。
   
  1. package com.clark.thread;  
  2.   
  3. public class MyThread implements Runnable{  
  4.     private int threadId;  
  5.       
  6.     public MyThread(int id){  
  7.         this.threadId = id;  
  8.     }  
  9.     @Override  
  10.     public synchronized void run() {  
  11.         //此时关键字synchronized锁住的是this对象,即当前运行线程对象本身  
  12.         for (int i = 0; i < 100; i++) {  
  13.             if(i % 10 ==0){  
  14.                 System.out.println();  
  15.             }  
  16.             System.out.print("Thread ID:"+this.threadId+":"+i+" ");  
  17.         }  
  18.     }  
  19.   
  20. }  
package com.clark.thread;

public class MyThread implements Runnable{
    private int threadId;
    
    public MyThread(int id){
        this.threadId = id;
    }
    @Override
    public synchronized void run() {
        //此时关键字synchronized锁住的是this对象,即当前运行线程对象本身
        for (int i = 0; i < 100; i++) {
            if(i % 10 ==0){
                System.out.println();
            }
            System.out.print("Thread ID:"+this.threadId+":"+i+" ");
        }
    }

}
  测试类:
  1. package com.clark.thread;  
  2.   
  3. public class ThreadDemo {  
  4.     public static void main(String[] args) throws InterruptedException {  
  5.                  //代码中创建了10个线程,而每个线程都持有this对象的对象锁,这不能实现线程的同步。  
  6.                  for (int i = 0; i < 10; i++) {  
  7.             new Thread(new MyThread(i)).start();  
  8.             Thread.sleep(1);  
  9.          }  
  10.     }  
  11. }  
package com.clark.thread;

public class ThreadDemo {
	public static void main(String[] args) throws InterruptedException {
                 //代码中创建了10个线程,而每个线程都持有this对象的对象锁,这不能实现线程的同步。
                 for (int i = 0; i < 10; i++) {
			new Thread(new MyThread(i)).start();
			Thread.sleep(1);
		 }
	}
}
     打印结果部分如下:其线程不是互斥访问的。因此没有达到资源多线程同步效果。。。
  1. Thread ID:1:60 Thread ID:1:61 Thread ID:1:62 Thread ID:1:63 Thread ID:1:64 Thread ID:1:65 Thread ID:1:66 Thread ID:1:67 Thread ID:1:68 Thread ID:1:69   
  2. Thread ID:1:70 Thread ID:1:71 Thread ID:1:72 Thread ID:1:73 Thread ID:1:74 Thread ID:1:75 Thread ID:1:76   
  3. Thread ID:1:77 Thread ID:1:78 Thread ID:1:79   
  4. Thread ID:1:80 Thread ID:1:81 Thread ID:2:0 Thread ID:1:82 Thread ID:1:83 Thread ID:1:84 Thread ID:1:85 Thread ID:1:86 Thread ID:1:87 Thread ID:1:88 Thread ID:1:89   
  5. Thread ID:1:90 Thread ID:1:91 Thread ID:1:92 Thread ID:1:93 Thread ID:1:94 Thread ID:1:95 Thread ID:2:1 Thread ID:2:2 Thread ID:2:3 Thread ID:2:4 Thread ID:2:5 Thread ID:2:6 Thread ID:2:7 Thread ID:2:8 Thread ID:2:9   
Thread ID:1:60 Thread ID:1:61 Thread ID:1:62 Thread ID:1:63 Thread ID:1:64 Thread ID:1:65 Thread ID:1:66 Thread ID:1:67 Thread ID:1:68 Thread ID:1:69 
Thread ID:1:70 Thread ID:1:71 Thread ID:1:72 Thread ID:1:73 Thread ID:1:74 Thread ID:1:75 Thread ID:1:76 
Thread ID:1:77 Thread ID:1:78 Thread ID:1:79 
Thread ID:1:80 Thread ID:1:81 Thread ID:2:0 Thread ID:1:82 Thread ID:1:83 Thread ID:1:84 Thread ID:1:85 Thread ID:1:86 Thread ID:1:87 Thread ID:1:88 Thread ID:1:89 
Thread ID:1:90 Thread ID:1:91 Thread ID:1:92 Thread ID:1:93 Thread ID:1:94 Thread ID:1:95 Thread ID:2:1 Thread ID:2:2 Thread ID:2:3 Thread ID:2:4 Thread ID:2:5 Thread ID:2:6 Thread ID:2:7 Thread ID:2:8 Thread ID:2:9 
从上述得知,要想实现线程同步,必须让这些线程去竞争一个唯一的共享对象锁。
  1. package com.clark.thread;  
  2.   
  3. public class MyThread implements Runnable{  
  4.     private int threadId;  
  5.     private Object object;//线程之间竞争使用的对象锁  
  6.     public MyThread(int id,Object object){  
  7.         this.threadId = id;  
  8.         this.object = object;  
  9.     }  
  10.     @Override  
  11.     public  void run() {  
  12.         /**  
  13.          * 将这个object对象的引用传递给每一个线程对象的lock成员变量  
  14.          * 从而每个线程的lock成员都指向同一个Object对象  
  15.          * 这样就可以让线程去竞争这个唯一的共享的对象锁,从而实现同步。  
  16.          */  
  17.         synchronized(object){  
  18.             for (int i = 0; i < 100; i++) {  
  19.                 if(i % 10 ==0){  
  20.                     System.out.println();  
  21.                 }  
  22.                 System.out.print("Thread ID:"+this.threadId+":"+i+" ");  
  23.             }  
  24.         }  
  25.     }  
  26.   
  27. }  
package com.clark.thread;

public class MyThread implements Runnable{
	private int threadId;
	private Object object;//线程之间竞争使用的对象锁
	public MyThread(int id,Object object){
		this.threadId = id;
		this.object = object;
	}
	@Override
	public  void run() {
		/**
		 * 将这个object对象的引用传递给每一个线程对象的lock成员变量
		 * 从而每个线程的lock成员都指向同一个Object对象
		 * 这样就可以让线程去竞争这个唯一的共享的对象锁,从而实现同步。
		 */
		synchronized(object){
			for (int i = 0; i < 100; i++) {
				if(i % 10 ==0){
					System.out.println();
				}
				System.out.print("Thread ID:"+this.threadId+":"+i+" ");
			}
		}
	}

}
  1. package com.clark.thread;  
  2.   
  3. public class ThreadDemo {  
  4.     public static void main(String[] args) throws InterruptedException {  
  5.         Object obj = new Object();  
  6.         for (int i = 0; i < 10; i++) {  
  7.             new Thread(new MyThread(i,obj)).start();  
  8.             Thread.sleep(1);  
  9.         }  
  10.     }  
  11. }  
package com.clark.thread;

public class ThreadDemo {
	public static void main(String[] args) throws InterruptedException {
		Object obj = new Object();
		for (int i = 0; i < 10; i++) {
			new Thread(new MyThread(i,obj)).start();
			Thread.sleep(1);
		}
	}
}
测试结果如下:
  1. Thread ID:5:60 Thread ID:5:61 Thread ID:5:62 Thread ID:5:63 Thread ID:5:64 Thread ID:5:65 Thread ID:5:66 Thread ID:5:67 Thread ID:5:68 Thread ID:5:69   
  2. Thread ID:5:70 Thread ID:5:71 Thread ID:5:72 Thread ID:5:73 Thread ID:5:74 Thread ID:5:75 Thread ID:5:76 Thread ID:5:77 Thread ID:5:78 Thread ID:5:79   
  3. Thread ID:5:80 Thread ID:5:81 Thread ID:5:82 Thread ID:5:83 Thread ID:5:84 Thread ID:5:85 Thread ID:5:86 Thread ID:5:87 Thread ID:5:88 Thread ID:5:89   
  4. Thread ID:5:90 Thread ID:5:91 Thread ID:5:92 Thread ID:5:93 Thread ID:5:94 Thread ID:5:95 Thread ID:5:96 Thread ID:5:97 Thread ID:5:98 Thread ID:5:99   
  5. Thread ID:6:0 Thread ID:6:1 Thread ID:6:2 Thread ID:6:3 Thread ID:6:4 Thread ID:6:5 Thread ID:6:6 Thread ID:6:7 Thread ID:6:8 Thread ID:6:9   
  6. Thread ID:6:10 Thread ID:6:11 Thread ID:6:12 Thread ID:6:13 Thread ID:6:14 Thread ID:6:15 Thread ID:6:16 Thread ID:6:17 Thread ID:6:18 Thread ID:6:19   
  7. Thread ID:6:20 Thread ID:6:21 Thread ID:6:22 Thread ID:6:23 Thread ID:6:24 Thread ID:6:25 Thread ID:6:26 Thread ID:6:27 Thread ID:6:28 Thread ID:6:29   
Thread ID:5:60 Thread ID:5:61 Thread ID:5:62 Thread ID:5:63 Thread ID:5:64 Thread ID:5:65 Thread ID:5:66 Thread ID:5:67 Thread ID:5:68 Thread ID:5:69 
Thread ID:5:70 Thread ID:5:71 Thread ID:5:72 Thread ID:5:73 Thread ID:5:74 Thread ID:5:75 Thread ID:5:76 Thread ID:5:77 Thread ID:5:78 Thread ID:5:79 
Thread ID:5:80 Thread ID:5:81 Thread ID:5:82 Thread ID:5:83 Thread ID:5:84 Thread ID:5:85 Thread ID:5:86 Thread ID:5:87 Thread ID:5:88 Thread ID:5:89 
Thread ID:5:90 Thread ID:5:91 Thread ID:5:92 Thread ID:5:93 Thread ID:5:94 Thread ID:5:95 Thread ID:5:96 Thread ID:5:97 Thread ID:5:98 Thread ID:5:99 
Thread ID:6:0 Thread ID:6:1 Thread ID:6:2 Thread ID:6:3 Thread ID:6:4 Thread ID:6:5 Thread ID:6:6 Thread ID:6:7 Thread ID:6:8 Thread ID:6:9 
Thread ID:6:10 Thread ID:6:11 Thread ID:6:12 Thread ID:6:13 Thread ID:6:14 Thread ID:6:15 Thread ID:6:16 Thread ID:6:17 Thread ID:6:18 Thread ID:6:19 
Thread ID:6:20 Thread ID:6:21 Thread ID:6:22 Thread ID:6:23 Thread ID:6:24 Thread ID:6:25 Thread ID:6:26 Thread ID:6:27 Thread ID:6:28 Thread ID:6:29 

从第二段代码可知,同步的关键是多个线程对象竞争同一个共享资源即可,上面的代码中是通过外部创建共享资源,然后传递到线程中来实现。我们也可以利用类成员变量被所有类的实例所共享这一特性,因此可以将
lock 用静态成员对象来实现,代码如下所示: 修改MyThread.java类如下

  1. package com.clark.thread;  
  2.   
  3. public class MyThread implements Runnable{  
  4.     private int threadId;  
  5.     private static Object object = new Object();//线程之间竞争使用的对象锁  
  6.     public MyThread(int id){  
  7.         this.threadId = id;  
  8.     }  
  9.     @Override  
  10.     public  void run() {  
  11.         <strong>/**  
  12.          * 将这个object对象的引用传递给每一个线程对象的lock成员变量  
  13.          * 从而每个线程的lock成员都指向同一个Object对象  
  14.          * 这样就可以让线程去竞争这个唯一的共享的对象锁,从而实现同步。  
  15.          */</strong>  
  16.         synchronized(object){  
  17.             for (int i = 0; i < 100; i++) {  
  18.                 if(i % 10 ==0){  
  19.                     System.out.println();  
  20.                 }  
  21.                 System.out.print("Thread ID:"+this.threadId+":"+i+" ");  
  22.             }  
  23.         }  
  24.     }  
  25.   
  26. }  
package com.clark.thread;

public class MyThread implements Runnable{
	private int threadId;
	private static Object object = new Object();//线程之间竞争使用的对象锁
	public MyThread(int id){
		this.threadId = id;
	}
	@Override
	public  void run() {
		<strong>/**
		 * 将这个object对象的引用传递给每一个线程对象的lock成员变量
		 * 从而每个线程的lock成员都指向同一个Object对象
		 * 这样就可以让线程去竞争这个唯一的共享的对象锁,从而实现同步。
		 */</strong>
		synchronized(object){
			for (int i = 0; i < 100; i++) {
				if(i % 10 ==0){
					System.out.println();
				}
				System.out.print("Thread ID:"+this.threadId+":"+i+" ");
			}
		}
	}

}
结果如下:
  1. Thread ID:0:0 Thread ID:0:1 Thread ID:0:2 Thread ID:0:3 Thread ID:0:4 Thread ID:0:5 Thread ID:0:6 Thread ID:0:7 Thread ID:0:8 Thread ID:0:9   
  2. Thread ID:0:10 Thread ID:0:11 Thread ID:0:12 Thread ID:0:13 Thread ID:0:14 Thread ID:0:15 Thread ID:0:16 Thread ID:0:17 Thread ID:0:18 Thread ID:0:19   
  3. Thread ID:0:20 Thread ID:0:21 Thread ID:0:22 Thread ID:0:23 Thread ID:0:24 Thread ID:0:25 Thread ID:0:26 Thread ID:0:27 Thread ID:0:28 Thread ID:0:29   
  4. Thread ID:0:30 Thread ID:0:31 Thread ID:0:32 Thread ID:0:33 Thread ID:0:34 Thread ID:0:35 Thread ID:0:36 Thread ID:0:37 Thread ID:0:38 Thread ID:0:39   
Thread ID:0:0 Thread ID:0:1 Thread ID:0:2 Thread ID:0:3 Thread ID:0:4 Thread ID:0:5 Thread ID:0:6 Thread ID:0:7 Thread ID:0:8 Thread ID:0:9 
Thread ID:0:10 Thread ID:0:11 Thread ID:0:12 Thread ID:0:13 Thread ID:0:14 Thread ID:0:15 Thread ID:0:16 Thread ID:0:17 Thread ID:0:18 Thread ID:0:19 
Thread ID:0:20 Thread ID:0:21 Thread ID:0:22 Thread ID:0:23 Thread ID:0:24 Thread ID:0:25 Thread ID:0:26 Thread ID:0:27 Thread ID:0:28 Thread ID:0:29 
Thread ID:0:30 Thread ID:0:31 Thread ID:0:32 Thread ID:0:33 Thread ID:0:34 Thread ID:0:35 Thread ID:0:36 Thread ID:0:37 Thread ID:0:38 Thread ID:0:39 

再来看第一段代码,实例方法中加入sychronized关键字封锁的是this对象本身,而在静态方法中加入sychronized关键字封锁的就是类本身。静态方法是所有类实例对象所共享的,因此线程对象在访问此静态方法时是互斥访问的,从而可以实现线程的同步,代码如下所示:

  1. package com.clark.thread;  
  2.   
  3. public class MyThread implements Runnable{  
  4.     private int threadId;  
  5.     public MyThread(int id){  
  6.         this.threadId = id;  
  7.     }  
  8.     @Override  
  9.     public  void run() {  
  10.         start(this.threadId);  
  11.     }  
  12.     private static synchronized void start(int threadId2) {  
  13.         for (int i = 0; i < 100; i++) {  
  14.             if(i % 10 == 0){  
  15.                 System.out.println();  
  16.             }  
  17.             System.out.print("Thread ID:"+threadId2+":"+i+" ");  
  18.         }  
  19.     }  
  20.   
  21. }  
package com.clark.thread;

public class MyThread implements Runnable{
	private int threadId;
	public MyThread(int id){
		this.threadId = id;
	}
	@Override
	public  void run() {
		start(this.threadId);
	}
	private static synchronized void start(int threadId2) {
		for (int i = 0; i < 100; i++) {
			if(i % 10 == 0){
				System.out.println();
			}
			System.out.print("Thread ID:"+threadId2+":"+i+" ");
		}
	}

}

结果如下=========

Thread ID:0:0 Thread ID:0:1 Thread ID:0:2 Thread ID:0:3 Thread ID:0:4 Thread ID:0:5 Thread ID:0:6 Thread ID:0:7 Thread ID:0:8 Thread ID:0:9 Thread ID:0:10 Thread ID:0:11 Thread ID:0:12 Thread ID:0:13 Thread ID:0:14 Thread ID:0:15 Thread ID:0:16 Thread ID:0:17 Thread ID:0:18 Thread ID:0:19 Thread ID:0:20 Thread ID:0:21 Thread ID:0:22 Thread ID:0:23 Thread ID:0:24 Thread ID:0:25 Thread ID:0:26 Thread ID:0:27 Thread ID:0:28 Thread ID:0:29 Thread ID:0:30 Thread ID:0:31 Thread ID:0:32 Thread ID:0:33 Thread ID:0:34 Thread ID:0:35 Thread ID:0:36 Thread ID:0:37 Thread ID:0:38 Thread ID:0:39 Thread ID:0:40 Thread ID:0:41 Thread ID:0:42 Thread ID:0:43 Thread ID:0:44 Thread ID:0:45 Thread ID:0:46 Thread ID:0:47 Thread ID:0:48 Thread ID:0:49 Thread ID:0:50 Thread ID:0:51 Thread ID:0:52 Thread ID:0:53 Thread ID:0:54 Thread ID:0:55 Thread ID:0:56 Thread ID:0:57 Thread ID:0:58 Thread ID:0:59

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值