[b][color=blue]零、一些概念[/color][/b]
[b]共享变量[/b]:一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。
[b]共享变量可见性[/b]:一个线程对共享变量值的修改,能够及时被其它线程看见。
实现的过程,线程1 将自己工作内存中的变量修改后,更新到主内存中,然后主内存将新值更新到线程2的工作内存中去。
[b]JMM[/b]:Java 内存模型(Java Memory Model)
[b]主内存[/b]:所有的变量都保存在主内存中。
[b]工作内存[/b]:每个线程都有自己独立的工作内存,保存了主内存中变量的一个copy (副本)
关系图如下:
[img]http://dl2.iteye.com/upload/attachment/0107/2825/026596b8-3019-3173-9714-d56818bb02bd.png[/img]
[b][color=blue]一、实现线程的两种方式[/color][/b]
Thd1.java
TestThd.java
[b][color=blue]二、共享变量线程间可见性实现[/color][/b]
线程解锁前,必须要把共享变量的最新值刷新到主内存中去。
线程加锁时,将清空工作内存中共享变量的值。从而使用共享变量时,需要从主内存中重新加载共享变量的最新值。
线程解锁前对共享变量的修改,在下次加锁时对其它线程可见。
1、synchronized 实现可见性
①:获取互斥锁
②:清空工作内存
③:从主内存中copy 共享变量的最新副本到工作内存中。
④:执行代码
⑤:将更改后的共享变量的值刷新到主内存中。
⑥:释放互斥锁
deposit() 和 withdraw() 函数都需要这个锁来进行操作,所以当一个函数运行时,另一个函数就被阻塞。请注意, checkBalance() 未作更改,它严格来讲是一个读函数。因为 checkBalance() 未作同步处理,所以任何其他方法都不会阻塞它,它也不会阻塞任何其他方法,不管那些方法是否进行了同步处理。
2、volatile 实现可见性
3、synchronized 与 volatile 的比较
> volatile 不需要加锁,不会阻塞线程,比synchronized 轻量级,所以执行效率高一些。
> 从内存可见性角度来看,volatile 读相当于加锁,写相当于解锁。
> synchronized 可以保证原子性和可见性,volatile 只能保证可见性,不能保证原子性
不错的文章:[url=http://www.blogjava.net/Werther/archive/2009/07/21/287656.html]http://www.blogjava.net/Werther/archive/2009/07/21/287656.html[/url]
[b]共享变量[/b]:一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量。
[b]共享变量可见性[/b]:一个线程对共享变量值的修改,能够及时被其它线程看见。
实现的过程,线程1 将自己工作内存中的变量修改后,更新到主内存中,然后主内存将新值更新到线程2的工作内存中去。
[b]JMM[/b]:Java 内存模型(Java Memory Model)
[b]主内存[/b]:所有的变量都保存在主内存中。
[b]工作内存[/b]:每个线程都有自己独立的工作内存,保存了主内存中变量的一个copy (副本)
关系图如下:
[img]http://dl2.iteye.com/upload/attachment/0107/2825/026596b8-3019-3173-9714-d56818bb02bd.png[/img]
[b][color=blue]一、实现线程的两种方式[/color][/b]
Thd1.java
public class Thd1 extends Thread {//继承Thread类创建线程
private long waitTime;
public Thd1(long wt){
this.waitTime=wt;
}
public void run(){
try {
Thread.sleep(waitTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread1");
}
}
[/code]
Thd2.java
[code="java"]public class Thd2 implements Runnable {//实现Runnable接口来创建线程
private long waitTime;
public Thd2(long wt){
this.waitTime=wt;
}
public void run() {
System.out.println("thread2");
try {
Thread.sleep(waitTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
TestThd.java
public class TestThd {//测试类
/**
* @param args
*/
public static void main(String[] args) {
Thd1 t1=new Thd1(3000);//继承Thread 类并重写run()的线程;
t1.start();
Thd2 t2=new Thd2(3000);//实现Runable 接口 重写run()的线程
Thread t=new Thread(t2);
t.start();
/*小结:线程启动方式都为start()。所以
* 第二种实现一个线程时也要得到thread的一个实例。
* 因为只有它有start().
*本人拙见:如有错误请各位指正,谢谢!
* */
}
}
[b][color=blue]二、共享变量线程间可见性实现[/color][/b]
线程解锁前,必须要把共享变量的最新值刷新到主内存中去。
线程加锁时,将清空工作内存中共享变量的值。从而使用共享变量时,需要从主内存中重新加载共享变量的最新值。
线程解锁前对共享变量的修改,在下次加锁时对其它线程可见。
1、synchronized 实现可见性
①:获取互斥锁
②:清空工作内存
③:从主内存中copy 共享变量的最新副本到工作内存中。
④:执行代码
⑤:将更改后的共享变量的值刷新到主内存中。
⑥:释放互斥锁
public class Account {
//共享变量
String holderName;
float amount;
/*构造方法*/
public Account(String name, float amt) {
holderName = name;
amount = amt;
}
/*存钱*/
public synchronized void deposit(float amt) {
amount += amt;
}
/*取钱*/
public synchronized void withdraw(float amt) {
amount -= amt;
}
/*查看金额*/
public float checkBalance() {
return amount;
}
}
deposit() 和 withdraw() 函数都需要这个锁来进行操作,所以当一个函数运行时,另一个函数就被阻塞。请注意, checkBalance() 未作更改,它严格来讲是一个读函数。因为 checkBalance() 未作同步处理,所以任何其他方法都不会阻塞它,它也不会阻塞任何其他方法,不管那些方法是否进行了同步处理。
2、volatile 实现可见性
3、synchronized 与 volatile 的比较
> volatile 不需要加锁,不会阻塞线程,比synchronized 轻量级,所以执行效率高一些。
> 从内存可见性角度来看,volatile 读相当于加锁,写相当于解锁。
> synchronized 可以保证原子性和可见性,volatile 只能保证可见性,不能保证原子性
不错的文章:[url=http://www.blogjava.net/Werther/archive/2009/07/21/287656.html]http://www.blogjava.net/Werther/archive/2009/07/21/287656.html[/url]