从严格意义上讲并无法真正的线程并发,只不过多个线程的轮流分配CPU的时间片,切换时间较短。
统一进程下的多个线程是共享同样的地址空间和数据的,又由于线程执行顺序的不可预知性,一个线程可能会修改其他线程正在使用的变量,这一方面是给数据共享带来了便利;另一方面,如果处理不当,会产生脏读,幻读等问题,好在Java提供了一系列的同步机制来帮助解决这一问题。如下面的例子:
public class threadtest{
public static void main(String[] args){
Runnable target=new thread01();
/*多线程并发操作,操作同一个数据S*/
Thread thread01 = new Thread(target,"-----线程01---------");
thread01.start();
Thread thread02 = new Thread(target,"-----线程02---------");
thread02.start();
Thread thread03 = new Thread(target,"-----线程03---------");
thread03.start();
Thread thread04 = new Thread(target,"-----线程04---------");
thread04.start();
}
}
class thread01 implements Runnable {
int s=0;
@Override
public void run() {
/*线程不安全情况,多个线程都会访问成员变量S,取得的值已经是变化的值,
* 执行后,会发现每个线程的计算结果不同*/
/* for(int i=0;i<10;i++){
s=s+i;
System.out.println(Thread.currentThread().getName());
}
System.out.println(Thread.currentThread().getName()+"s值为"+s);
s=0;
*/
/*解决线程安全的方式*/
synchronized (this) {
for(int i=0;i<10;i++){
s=s+i;
System.out.println(Thread.currentThread().getName());
}
System.out.println(Thread.currentThread().getName()+"s值为"+s);
s=0;
}
}
}
解决线程安全的问题可以使用synchronize方法和synchronize语句块解决,如上图。
使用synchronize时,如 synchronize修饰的A语句块调用了同样使用synchronize修饰的B语句,同样在B语句中也调用了A语句。多线程调用时就会放生了一种死锁现象。解决死锁,使用notify()方法和notifyAll()方法,通知其他的线程可以使用这个锁标识(理解还不是很好,先记录下,在详细更新)