线程同步synchronized和volatile

java多线程特性

线程同步具有两个特性:可见性和有序性
java线程间的通信是通过共享变量实现的,假如多个线程共享某个Object对象,该对象被创建在主内存(堆内存)中,每个线程都有自己的工作内存(线程栈). 当线程操作Object对象时,首先从主内存拷贝对象副本到工作内存中,再执行修改变量的代码,最后把工作内存中的Object刷新到主内存中. 假如多个线程都保留Object对象的副本,若某时刻修改Object变量,其他线程也能够看到被修改后的值,此为可见性. 多线程并发执行时,cpu对线程的调度是随机的,最经典的例子是银行汇款问题,我们需要保证取款线程和汇款线程有序的进行,此为有序性.

synchronized

下面用代码说明线程同步的问题

public class TraditionalThreadSynchronized {
    public static void main(String[] args) {
        final Outputter output = new Outputter();
        new Thread() {
            public void run() {
                output.output("zhangsan");
            };
        }.start();      
        new Thread() {
            public void run() {
                output.output("lisi");
            };
        }.start();
    }
}
class Outputter {
    public void output(String name) {
        // TODO 为了保证对name的输出不是一个原子操作,这里逐个输出name的每个字符
        for(int i = 0; i < name.length(); i++) {
            System.out.print(name.charAt(i));
            // Thread.sleep(10);
        }
    }
}

程序的运行结果为zhlainsigsan,显然与预期结果不相符,这就是线程同步问题. 我们希望线程执行完output方法后再切换到其他线程. java使用synchronized关键字保证某段代码在不同线程间的执行是互斥的.

  • 使用synchronized将需要互斥的代码块包含起来
{
    synchronized (this) {
        for(int i = 0; i < name.length(); i++) {
            System.out.print(name.charAt(i));
        }
    }
}
  • synchronized加在需要互斥的方法上
public synchronized void output(String name) {
    // TODO 线程输出方法
    for(int i = 0; i < name.length(); i++) {
        System.out.print(name.charAt(i));
    }
}

这种方式相当于用this锁住整个方法内的代码块,当修饰静态方法时,等价于用xxx.class锁住整个方法内的代码块,用synchronized修饰的代码块可以看做原子操作.
线程执行互斥方法的过程如下:
1. 获取同步锁
2. 清空工作内存
3. 从主内存拷贝对象副本到工作内存
4. 执行代码
5. 刷新主内存
6. 是放同步锁

由此可见synchronized既保证共享内存的可见性,又保证程序的有序性.

volatile

volatile是第二种java实现线程同步的机制.

class Test {
    static volatile int i = 0, j = 0;
    static void one() {
        i++;
        j++;
    }
    static void two() {
        System.out.println("i=" + i + " j=" + j);
    }
}

one方法和two方法还会并发执行,但加上volatile修饰后,可以将共享变量i和j的改变直接响应到主内存中,但在two方法获取到变量i和获取变量j的值的这段时间内,one方法可能会被执行多次,导致j的值大于i. 所以volatile仅保证线程间共享内存的可见性,不能保证并发的有序性.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值