从严格意义上讲并无法真正的线程并发,只不过多个线程的轮流分配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()方法,通知其他的线程可以使用这个锁标识(理解还不是很好,先记录下,在详细更新)