java线程资源共享的问题晕了,大慈大悲的观音菩萨请救我脱离苦海吧TUT

karrie 发布于 2013/11/10 16:24
阅读 425
收藏 1
两种写法,我感觉区别不大,为什么第一个不行?

要实现的功能是:

设计4个线程,其中两个线程每次对j增加1,
     * 另外两个线程对j每次减少1。写出程序。


第一个代码
package it_cast;

public class ThreadExercise28 {
	/*多个线程共享数据*/
	/**
	 * 设计4个线程,其中两个线程每次对j增加1,
	 * 另外两个线程对j每次减少1。写出程序。
	 * 
	 */
	private int j=0;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ThreadExercise28 tt=new ThreadExercise28();
		add a=tt.new add();
		minus m=tt.new minus();
		for(int i=0;i<2;i++)
		{
		//new Thread(new add(j)).start();
		//new Thread(new minus(j)).start();
		new Thread(a).start();
		new Thread(m).start();
	
		}
	}
	class add implements Runnable
	{
		
		
		public synchronized void run() {
			
			for(int i=0;i<50;i++)
			{
				
					j++;
				
				System.out.println(Thread.currentThread().getName()+"j+1后的值为:"+j);
			}
		}
		
		
	}
	 class minus implements Runnable
	{
		
		public synchronized void run() {
			
			for(int i=0;i<50;i++)
			{
				
					j--;
				
				System.out.println(Thread.currentThread().getName()+"j-1后的值为:"+j);
			}
		}
		
		
	}

}
第二段代码
package exercise;


public class ThreadExercise28 {
 /*多个线程共享数据*/
 /**
 * 设计4个线程,其中两个线程每次对j增加1,
 * 另外两个线程对j每次减少1。写出程序。
 * 
 */
 private int j=0;
 public static void main(String[] args) {
 // TODO Auto-generated method stub
 ThreadExercise28 tt=new ThreadExercise28();
 add a=tt.new add();
 //No enclosing instance of type ThreadExercise28 is accessible. 
 //Must qualify the allocation with an enclosing instance of type ThreadExercise28 (e.g. x.new A() where x is an instance of 
 //ThreadExercise28).
 minus m=tt.new minus();
 for(int i=0;i<2;i++)
 {
 //new Thread(new add(j)).start();
 //new Thread(new minus(j)).start();
 new Thread(a).start();
 new Thread(m).start();
 
 }
 }
 private synchronized void a()
 {
 for(int i=0;i<50;i++)
 {
 j++;
 
 System.out.println(Thread.currentThread().getName()+"j+1后的值为:"+j);
 }
 
 }
 private synchronized void m()
 {
 for(int i=0;i<50;i++)
 {
 j--;
 
 System.out.println(Thread.currentThread().getName()+"j-1后的值为:"+j);
 }
 
 }
 class add implements Runnable
 {
 public void run() {
 // TODO Auto-generated method stub
 a();
 }
 
 }
 class minus implements Runnable
 {
 
 public void run() {
 
 m();
 }
 
 
 }


}
加载中
0
徐春鹏
徐春鹏

引用来自“karrie”的答案

引用来自“徐春鹏”的答案

synchronized    加锁的范围不一样  两个函数两个锁 给一个生命周期大于这两个函数的变量加锁就好了吧  你要保护的是共享变量
救苦救难的大神,能帮我解释一下这两段为什么结果不同么?为什么不能直接在run函数声明那儿+synchronized啊?我是要保护共享变量j,所以给run函数加锁不就行了么?为什么非得就提到里面的代码呢?
public void run() {
			synchronized (ThreadExercise28.class){
			for(int i=0;i<50;i++)
			{
				 
					j--;
				
					
				
				System.out.println(Thread.currentThread().getName()+"j-1后的值为:"+j);
			}
			}
		}
片段二
public synchronized void run() {
 //synchronized (ThreadExercise28.class){
 for(int i=0;i<50;i++)
 {
  
 j--;
 
 
 
 System.out.println(Thread.currentThread().getName()+"j-1后的值为:"+j);
 }
 //	}
在run那加上这个关键字  也就是 把这个run 函数 上了一个函数锁 这个函数在同一时刻只能有一个线程访问,但是 你这个run函数没有其他线程去调用 只有一个线程调用了 
synchronized (ThreadExercise28.class) 这样的锁  是对这个类加了个锁 也就是说在同一时刻只能有一个线程即持有该类锁的线程对你保护的代码进行访问 这个作用域就很大了
还是说说你的第一个代码吧  你声明了两个内部类 这两个内部类去共享你的j变量 你的锁锁上的是两个内部类的run方法 也就是线程默认调用的方法,  new Thread(a).start(); new Thread(m).start(); 你创建了两个线程去跑着两个runnable 没有产生连个线程同时访问你的加锁代码的部分 也就是这两个线程是公平竞争CPU的  当“加”线程时间片完成 虽然还是持有一个run函数范围的锁 但是下一次线程调用可能还是加 但是也可能是“减” 因为"减"没有访问“加”所持有的锁的代码段。所以是不同的了
karrie
karrie
非常感谢,感觉思路有清晰了很多!谢谢你!
0
徐春鹏
徐春鹏
synchronized    加锁的范围不一样  两个函数两个锁 给一个生命周期大于这两个函数的变量加锁就好了吧  你要保护的是共享变量
karrie
karrie
先开始没看懂,现在懂了,谢谢!
0
karrie
karrie

引用来自“徐春鹏”的答案

synchronized    加锁的范围不一样  两个函数两个锁 给一个生命周期大于这两个函数的变量加锁就好了吧  你要保护的是共享变量
救苦救难的大神,能帮我解释一下这两段为什么结果不同么?为什么不能直接在run函数声明那儿+synchronized啊?我是要保护共享变量j,所以给run函数加锁不就行了么?为什么非得就提到里面的代码呢?
public void run() {
			synchronized (ThreadExercise28.class){
			for(int i=0;i<50;i++)
			{
				 
					j--;
				
					
				
				System.out.println(Thread.currentThread().getName()+"j-1后的值为:"+j);
			}
			}
		}
片段二
public synchronized void run() {
 //synchronized (ThreadExercise28.class){
 for(int i=0;i<50;i++)
 {
  
 j--;
 
 
 
 System.out.println(Thread.currentThread().getName()+"j-1后的值为:"+j);
 }
 //	}
0
小白小霸王
小白小霸王
我就看见 itcast了
0
风林火山
风林火山
看你的代码第一反应是我去,JAVA出新语法了,仔细一看,你定义的内部类啊,还是小写的。add,和 minus 都是类啊。感觉你对多线程的理解错了。 建议类ThreadExercise28 中两个 sychronized方法  add,和minus。这个类跟线程没有任何关系,而是被线程操作的。你需要再创建一个线程类ThreadClient extends Thread 里边调用add或者 minus。回去看看说吧。
karrie
karrie
确实,内部类不太熟悉,总是当成方法写成小写的orz谢谢你的回答~
0
excepiton
excepiton
synchronized的锁对象是哪个没搞清楚吧
返回顶部
顶部