public class 多线程的错误演示  implements Runnable {
private int count =10;

public static void main(String[] arg){
Thread[] t = new Thread[6];
///////////////////////////////////
//继承接口Runnable会产生脏读现象 多线程的错误演示 tr = new 多线程的错误演示();
for(int i=0;i<3;i++){
t[i] = new Thread(tr);
t[i].setName("Runnable-->" + i);
t[i].start();
} ///////////////////////////////////
//继承类Thread,就不会产生脏读现象
for(int i=3;i<6;i++){
t[i] = new MyThread("Thread-->" + i);
t[i].start();
}
}
public void run() {
while (count>=0){
try{Thread.sleep(100);}catch(Exception e){;}
MyThread.p(Thread.currentThread().getName() + ":" + (count--));
}
}
}class MyThread extends Thread
{
private int count =10;
public MyThread(String name){
super(name);
} public void run(){
while (count>=0){
try{sleep(100);}catch(Exception e){;}
p(getName() + ":" + (count--));
}
} public static void p(String s){
System.out.println(s);
}
};

解决方案 »

  1.   

    >1.什么是线程安全?线程安全是怎么完成的(原理)?线程安全就是说多线程访问同一代码,不会产生不确定的结果。编写线程安全的代码是低依靠线程同步。>2.为什么继承接口Runnable会产生脏读现象,继承类Thread,就不会产生脏读现象? 楼主的这个认识是错误的,两者是一样的,只是使用接口更加灵活些。如果楼主在使用中产生不同的效果,表明是楼主的使用方法导致了不同的效果,与采用哪一种方式无关。
      

  2.   

    楼主的两段代码不是等效的,在接口方式中,线程有一个共享的数据成员,即:
    private int count =10;而在继承方式中,线程之间没有共享的成员,而是各线程各自有一个私有成员,即:
    private int count =10;楼主的代码刚好是一个好例子,说明了何时需要考虑线程同步,并在一定程序上说明了怎样才能编写出线程安全的代码。在多线程环境中,当各线程不共享数据的时候,那么一定是线程安全的。问题是这种情况并不多见,在多数情况下需要共享数据,这时就需要进行适当的同步控制了。
      

  3.   

    线程安全一般都涉及到synchronized
    就是一段代码同时只能有一个线程来操作
    不然中间过程可能会产生不可预制的结果
      

  4.   

    首先要明白线程的工作原理,jvm有一个main memory,而每个线程有自己的working memory,一个线程对一个variable进行操作时,都要在自己的working memory里面建立一个copy,操作完之后再写入main memory。多个线程同时操作同一个variable,就可能会出现不可预知的结果。根据上面的解释,很容易想出相应的scenario。
    而用synchronized的关键是建立一个monitor,这个monitor可以是要修改的variable也可以其他你认为合适的object比如method,然后通过给这个monitor加锁来实现线程安全,每个线程在获得这个锁之后,要执行完 load到workingmemory -> use&assign -> store到mainmemory 的过程,才会释放它得到的锁。这样就实现了所谓的线程安全。
      

  5.   

    C++里每个类的方法相对第它的实例是公共的,只有数据才是每个实例私有的.java里我没找到有相关说明,不知java是不是这样实现的.那么干脆每个线程都不使用静态变量,都创建实例,应该可以避免线程安全问题了吗?
      

  6.   

    操作系统里面对线程这个问题讨论的比较细,它有一个临界区专门来处理同步数据,老师以前好像讲过,JAVA是用monitor来监视syncronized变量的,具体的楼主可以查查API,学习~
      

  7.   

    线程安全就是在共享数据区不能同时有多个线程进行操作。要用关键字syncornized进行控制。
      

  8.   

    chrisj() 把线程的工作原理解释的很清楚,但我觉得syncornized不是实现线程安全的关键所在.如果在一个应用里某个类只能创建一个实例,而且要保证这个类必须是线程安全的。那岂不是每个类方法都要加syncornized关键字,它的变量如果能实现同步?
    另外当A线程执行此类的a()方法,另外当B线程执行此类的B()方法,同时a()及b()方法都会改变此类的private变量,这怎么能叫线程安全呢?
      

  9.   

    没有听说过继承Thread不会产生脏读,而实现Runnable会产生脏读现象! 如果是这样,干嘛还要提供两位实现线程的方式呢?
      

  10.   

    楼上,WxmJun(胡扯之) 在上面已经承认了这个错误了,呵呵WxmJun(胡扯之) 提出了另外一个问题,解决这个问题的方法是用volatile variable.
      

  11.   

    to chrisj() :
    能具体解释一下volatile variable吗?