1、线程同步背景

程序在运行过程中,会将运算需要的数据(如:常量、变量等)从物理内存复制一份到CPU的高速缓存中,这样CPU就可以直接在高速缓存中读写数据、进行运算,最后当运算结束时、再将高速缓存中的数据刷新到物理内存;多线程访问同一变量(或内存)时,由于每个线程都有自己独立的高速缓存(对应一个或多个CPU),这样每个线程对应的高速缓存中的数据刷新到物理内存时就有可能相互覆盖、造成混乱,这就是典型的“缓存一致性问题”(也称:竞争条件);Java虽然在虚拟机(JVM)上运行,但虚拟机(JVM)一样存在“缓存一致性问题”

2、线程同步定义

线程同步,即多线程在对同一变量(或内存)访问时、必须同时满足以下3个特性:

a、原子性

一个或多个操作要么全部执行(执行过程不会被任何因素打断),要么全部都不执行

b、可见性

当多个线程访问同一个变量(或内存)时,一个线程修改了这个变量(或内存)的值,其他线程能够立即看到修改后的值

c、有序性

多线程执行相同代码块时,各线程依次串行执行该代码块;由于编译器存在“指令重排序”,多线程执行相同代码块时,如果不串行执行就有可能出现错误

3、线程同步方式

a、volatile变量

volatile变量即类中被关键字volatile修饰的静态(或非静态)成员变量;这种成员变量被多线程访问时,只能保证可见性、不能完全保证原子性及有序性,因此使用volatile变量不能做到完全同步(严格讲、不叫同步)、使用场景比较有限

b、同步代码块

使用“synchronized(对象){}”格式,表示“{}”中代码块用该对象的内置锁进行加锁、代码块执行完后内置锁将自动解锁

c、同步方法

使用synchronized关键字修饰方法, 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁就会保护整个方法,在调用该方法前,需要获得内置锁,否则就处于阻塞状态;注意:如果是同类多个不同线程对象同步,同步方法要声明为属于类的静态方法(static修饰),否则该方法只属于某个线程对象,做不到线程对象之间的同步、只能做到在该线程对象内部同步

d、重入锁

JDK5.0中通过新增java.util.concurrent包来支持;ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 它与“同步代码块”、“同步方法”具有相同的基本行为和语义,并且扩展了其能力;ReenreantLock类的常用方法有:

ReentrantLock()-创建一个ReentrantLock实例

lock()-获得锁

unlock()-释放锁

注意:ReentrantLock()还有一个可以创建公平锁的构造方法,但由于会大幅度降低程序运行效率,不推荐使用

e、更多

更多线程同步方式(如:Semaphore)见:java.util.concurrent包

4、线程同步案例演示

ThreadSynCases.java

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 线程类定义,用于线程同步(volatile变量-状态标记)应用案例演示
 */
class ThreadVolatile extends Thread
{
 //计数器,用于记录线程执行情况
 private static int count = 10;
 //停止标志
 private volatile boolean stopFlag = false;
 /**
 * 停止执行 
 */
 public void stopExecute() 
 {
 stopFlag = true;
 }//public void stopExecute(
 /**
 * 重写Thread.run()方法 
 */
 public void run() 
 {
 while (!stopFlag) 
 { 
 if(count > 0)
 {
 try 
 {
 //线程休眠10毫秒
 Thread.sleep(10);
 } 
 catch (InterruptedException e) 
 {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 //打印count变量
 System.out.println("Count="+count+" "); 
 //使count变量自减,当自减为0时,退出线程
 if (--count <= 0) 
 {
 return;
 } 
 }
 else
 {
 return;
 }//if(count > 0)..else 
 //..
 }//while (!stopFlag) 
 }//public void run() 
}//class ThreadVolatile extends Thread
/**
 * 单例类定义,用于线程同步(volatile变量-双重检查)应用案例演示
 */
class SingletonVolatile
{
 //单例对象
 private volatile static SingletonVolatile instance = null;
 /**
 * 获取单例对象;这里使用双重检查;如果直接对整个方法体使用同步控制、而不使用双重检查,逻辑上也没问题,只是由于同
 * 步控制开销较大、多线程访问该方法时效率较低;如果一旦如该方法使用双重检查,相关变量(如:该方法instance)就
 * 必须用volatile关键字修饰,否则对该变量的访问就有“缓存一致性问题”
 * @return
 * 单例对象
 */
 public static SingletonVolatile gainInstance() 
 {
 //检查1
 if(null == instance) 
 {
 //同步控制
 synchronized (SingletonVolatile.class) 
 {
 //检查2
 if(null == instance)
 {
 instance = new SingletonVolatile();
 }
 }
 }
 return instance;
 }//public static SingletonVolatile gainInstance(
 /**
 * 打印输出 
 */
 public void printSelf() 
 {
 System.out.println("我是一个单例类对象!"); 
 }
 /**
 * 构造方法
 */
 private SingletonVolatile() 
 {
 }
}//class SingletonVolatile extends Thread
/**
 * 线程类定义,用于线程同步(同步代码块)应用案例演示
 */
class ThreadClass7 extends Thread
{
 //计数器,用于记录线程执行情况
 private static int count = 10;
 /**
 * 重写Thread.run()方法
 */
 public void run() 
 {
 while (true) 
 { 
 synchronized("同步代码块")
 {
 if(count > 0)
 {
 try 
 {
 //线程休眠10毫秒
 Thread.sleep(10);
 } catch (InterruptedException e) 
 {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 //打印count变量
 System.out.println("Count="+count+" "); 
 //使count变量自减,当自减为0时,退出线程
 if (--count <= 0) 
 {
 return;
 } 
 }
 else
 {
 return;
 }//if(count > 0)..else 
 //..
 }//synchronized(
 }//while (true) 
 }//public void run() 
}//class ThreadClass7 extends Thread
/**
 * 线程类定义,用于线程同步(同步方法)应用案例演示
 */
class ThreadClass8 extends Thread
{
 //计数器,用于记录线程执行情况
 private static int count = 10;
 /**
 * 重写Thread.run()方法 
 */
 public void run() 
 {
 while (true) 
 { 
 //同步方法
 if(!synRun())
 {
 return;
 //..
 }
 }//while (true) 
 }//public void run() 
 /**
 * 定义同步方法(注意:如果是同类多个不同线程对象同步,同步方法要声明为static类型的,否则该方法只属于某个线程对
 * 象,做不到线程对象之间的同步、只能做到在该线程对象内部同步)
 * @return
 * 退出,返回false;否则,返回true
 */
 private synchronized static boolean synRun() 
 {
 if(count > 0)
 {
 try 
 {
 //线程休眠10毫秒
 Thread.sleep(10);
 } catch (InterruptedException e) 
 {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 //打印count变量
 System.out.println("Count="+count+" "); 
 //使count变量自减,当自减为0时,退出线程
 if (--count <= 0) 
 {
 return false;
 } 
 }
 else
 {
 return false;
 }//if(count > 0)..else 
 return true;
 }//public synchronized boolean synRun() 
}//class ThreadClass8 extends Thread
/**
 * 线程类定义,用于线程同步(重入锁)应用案例演示
 */
class ThreadClassLock extends Thread
{
 //计数器,用于记录线程执行情况
 private static int count = 10;
 //声明重入锁
 private static Lock lock = new ReentrantLock(); 
 /**
 * 重写Thread.run()方法 
 */
 public void run() 
 {
 while (true) 
 { 
 try 
 {
 //加锁
 lock.lock(); 
 if(count > 0)
 {
 try 
 {
 //线程休眠10毫秒
 Thread.sleep(10);
 } catch (InterruptedException e) 
 {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }
 //打印count变量
 System.out.println("Count="+count+" "); 
 //使count变量自减,当自减为0时,退出线程
 if (--count <= 0) 
 {
 return;
 } 
 }
 else
 {
 return;
 }//if(count > 0)..else 
 //..
 } 
 finally 
 { 
 //解锁 
 lock.unlock();
 } 
 }//while (true) 
 }//public void run() 
}//class ThreadClassLock extends Thread
/**
 * 线程同步案例类
 */
public class ThreadSynCases 
{
 //线程创建,执行控制时间
 //private static final long CREATE_CTRL_TIME = 20;
 /**
 * 等待一会时间,用于执行顺序控制
 * @param millis :[IN]等待的时间(单位:毫秒)
 */
 protected static void waitForMoment(long millis)
 {
 try 
 {
 Thread.sleep(millis);
 } catch (InterruptedException e) 
 {
 // TODO Auto-generated catch block
 e.printStackTrace();
 } 
 }//protected static void waitForMoment(
 public static void main(String[] args) 
 {
 System.out.println("//线程同步(volatile变量-状态标记),应用案例演示//"); 
 //实例化线程对象
 ThreadVolatile threadVolatile = new ThreadVolatile();
 //线程启动
 threadVolatile.start(); 
 //执行一会时间
 waitForMoment(50); 
 //停止执行
 threadVolatile.stopExecute();
 //等待一会时间,让线程结束
 waitForMoment(200); 
 System.out.println("//线程同步(volatile变量-双重检查),应用案例演示//"); 
 //实例化单例类对象
 SingletonVolatile singletonVolatile =SingletonVolatile.gainInstance();
 //打印输出
 singletonVolatile.printSelf();
 System.out.println("//线程同步(同步代码块),应用案例演示//"); 
 //实例化线程对象
 ThreadClass7 thread71 = new ThreadClass7();
 ThreadClass7 thread72 = new ThreadClass7(); 
 ThreadClass7 thread73 = new ThreadClass7(); 
 ThreadClass7 thread74 = new ThreadClass7(); 
 //线程启动
 thread71.start(); 
 thread72.start();
 thread73.start();
 thread74.start();
 //等待一会时间,让线程结束
 waitForMoment(200); 
 System.out.println("//线程同步(同步方法),应用案例演示//"); 
 //实例化线程对象
 ThreadClass8 thread81 = new ThreadClass8();
 ThreadClass8 thread82 = new ThreadClass8(); 
 ThreadClass8 thread83 = new ThreadClass8(); 
 ThreadClass8 thread84 = new ThreadClass8(); 
 //线程启动
 thread81.start(); 
 thread82.start();
 thread83.start();
 thread84.start();
 //等待一会时间,让线程结束
 waitForMoment(200); 
 System.out.println("//线程同步(重入锁),应用案例演示//"); 
 //实例化线程对象
 ThreadClassLock threadLock1 = new ThreadClassLock();
 ThreadClassLock threadLock2 = new ThreadClassLock(); 
 ThreadClassLock threadLock3 = new ThreadClassLock(); 
 ThreadClassLock threadLock4 = new ThreadClassLock(); 
 //线程启动
 threadLock1.start(); 
 threadLock2.start();
 threadLock3.start();
 threadLock4.start();
 //等待一会时间,让线程结束
 waitForMoment(200); 
 }//public static void main(
}//public class ThreadSynCases

运行以上代码,可得到如下结果:




j2ee线程同步架构 java线程同步的原理_java 线程同步


j2ee线程同步架构 java线程同步的原理_java 线程同步_02