您的位置:首页 > 编程语言 > Java开发

我是菜鸟:java多线程join方法,volatile以及synchronized关键字理解

2015-05-01 08:49 591 查看
join方法理解

synchronized 关键字的使用
synchronized与static之间的关系

synchronized与锁
锁的类型类锁 and 对象锁

线程同步与notify和wait方法

volatile关键字的使用

join方法理解

当一个子线程调用join()方法后,主线程等待子线程终止,子线程调用了join()方法后,余下的代码,只有等到子线程结束了才能执行。

/** Join()方法的使用。
*
* */
public class MultTread {
public static void main(String[] args){
Thread myThread = new Thread(new myRunable1());
myThread.start();
for(int i=1;i<6;i++){
try{
Thread.sleep(100);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("<<<<<<<:"+i+"出发了。");
if(3==i){
try{
myThread.join(); //主线程等待子线程终止,子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
}

class myRunable1 implements Runnable{

@Override
public void run() {
// TODO Auto-generated method stub
for(int i=1;i<6;i++)
{
try{
Thread.sleep(100);
}catch(Exception e){e.getMessage();}
System.out.println(">>>>:"+i+"紧急出发了。");
}

}

}


synchronized 关键字的使用

被synchronized修饰的方法叫做同步方法,其能够解决同步问题的原因在于java内置锁有关,如果方法声明为synchronized后,内部锁会保护整个方法,即在调用该方法前需要获得内部锁,否则就处于阻塞状态。

synchronized与static之间的关系

静态方法:同一个类中,所有被synchronized修饰的静态方法,他们在类范围是同步的。也就是同一时间内,只有一个线程调用他们中的任意一个方法。

非静态方法:对于同一个类中所有被synchronized修饰的非静态方法,他们在同一个对象上是同步的

synchronized与锁

锁的类型—类锁 and 对象锁

对象锁是用于非静态同步方法的。在Java平台中,会给每个拥有同步方法的对象分配一个对象锁,即内部锁。

类锁与对象锁唯一不同的是类锁是每个有静态同步方法的类才拥有一个。

线程同步与notify()和wait()方法

wait和notify是object类的2个方法。

* wait()方法:让线程进入挂起状态。

* notify()方法:唤醒是因为在同一个对象上调用wait()方法而处于挂起的状态的线程,让线程继续执行下去

note: 必须在一个获得了此对象锁的代码内部才能调用这个对象的wait()和notify方法。注意wait-notify的顺序,防止程序进入死锁状态。

volatile关键字的使用

volatile关键字解释:volatile 对域变量的访问提供了一种免锁机制,相当于告诉JVM该域可能会被其它线程更新,因此每次使用该域就要重新计算,而不是使用寄存器中的值。volatile不会提供任何原子操作,也不能用final类型的变量。但是volatile 不能保证原子操作,即最终结果可能与预期不符合。对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的

线程对变量的处理过程:

其中有一个内存区域是jvm虚拟机栈,每一个线程运行时都有一个线程栈,线程栈保存了线程运行时候变量值信息。 当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改 副本变量的值,在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。

博文[java中volatile关键字的含义]讲解的不错,挺详细的,在此记录下,谢谢原博主。

下面是对synchronized和volatile关键字测试:

/**
* 线程同步
*/

public class MultTread{
public static void main(String []args){
Bank myBank = new Bank();
Thread myTread = new Thread(new myTread2(myBank));
Thread myTread1 = new Thread(new myTread2(myBank));
myBank.deposit(200);
System.out.println(myBank.getAccount());
myTread.start();
myTread1.start();

}
}

class Bank{
/**
* 如果变量定义为普通的变量,如private int account = 100, 则在对其改写的方法中添加synchronized
* 关键字。如果在方法前不用synchronized 关键字修饰,那么可以用volatile 对变量进行修饰。
*
* 其定义如下:
* private volatile int account = 100;
*/

private int account = 100;

/**
* account += money,总共有3步执行:1、读取account值; 2、求和; 3、存入account。在多线程
* 中,可能同时读取account值,这样最终的值会少计算。
*
* @param money
*/
public synchronized void deposit(int money){
account += money;
}
public int getAccount(){
return account;
}
}
class myTread2 implements Runnable{
private Bank mybank;

public myTread2(Bank bank){
this.mybank = bank;
}
public void run(){
for(int i=0;i<10;i++)
{
try{
Thread.sleep(100);
}catch(Exception e){e.getMessage();}
mybank.deposit(10);
System.out.println("线程号:"+Thread.currentThread().getId()+"金额: "+mybank.getAccount());
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐