java-多线程深入(二)互斥性和可见性

(一)互斥性

互斥性,即原子性。原子,指最小的物质,具体不可再分性。

CPU运算中,对多线程进行时间片分割执行,一个程序块执行时不可分割,即满足互斥性原子性。

java中保证互斥性的方法:

1.用sychronized锁住程序块,实行互斥

synchronized (lock) {
    a++;
}

2.用Atomic对变量操作实行互斥

public final static AtomicInteger TEST_INTEGER = new AtomicInteger(1);  

    public static void main(String []args) throws InterruptedException {
        final Thread []threads = new Thread[20];
         for(int i = 0 ; i < 20 ; i++) {
             final int num = i;
             threads[i] = new Thread() {
                 public void run() {
                    int now = TEST_INTEGER.incrementAndGet();
                    System.out.println("我是线程:" + num + ",我得到值了,增加后的值为:" + now);
                 }
             };
             threads[i].start();
         }
         for(Thread t : threads) {
             t.join();
         }
         System.out.println("最终运行结果:" + TEST_INTEGER.get());
    }  

TEST_INTEGER在多线程操作中,最终结果不会出现偏差。

JDK的文档中说:“设计原子类主要用作各种块,用于实现非阻塞数据结构和相关基础结构类。compareAndSet()方法不是锁定的常规替换方法。仅当对象的重要更新限于单个变量时才应用它”。

(二)可见性

cpu和内存速度相差过高,引入缓存(cache、寄存器等);一个线程由线程id、指令计数器PC、寄存器集合和堆栈构成,详见《程序员的自我修养》

每个线程有自己的工作内存,修改进程主内存的值,都需要拷贝到工作内存修改后,再回写,其他线程可能出现,读取到未回写的脏数据这种情况。

/**
 * 多线程可见性测试
 *
 * @author peter_wang
 * @create-time 2015-1-12 下午3:56:29
 */
public class ThreadVisableDemo {
    private static int a = 0;

    static class GetNumThread
        extends Thread {
        @Override
        public void run() {
            System.out.println(a);//B1
        }
    }

    static class ChangeNumThread
        extends Thread {
        @Override
        public void run() {
            a = 1;//A1,A2
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        GetNumThread getNumThread = new GetNumThread();
        ChangeNumThread changeNumThread = new ChangeNumThread();
        changeNumThread.start();//C1
        getNumThread.start();//C2
    }

}

执行结果:输出0或者1

A1读取完数据进行操作,写入到线程A工作内存写缓存中,不一定实时刷新主内存中a的值,B1可能读取到旧数据。

java中保证可见性的方法:

1.用sychronized锁住程序块,实行互斥

static class GetNumThread
        extends Thread {
        @Override
        public void run() {
            synchronized (ThreadVisableDemo.class) {
                System.out.println(a);// B1
            }
        }
    }

    static class ChangeNumThread
        extends Thread {
        @Override
        public void run() {
            synchronized (ThreadVisableDemo.class) {
                a = 1;// A1,A2
            }
        }
    }

2.使用volatile,保证变量可见性

private static volatile int a = 0;

3.使用Atomic对变量操作,实现可见性

时间: 2024-12-29 11:27:28

java-多线程深入(二)互斥性和可见性的相关文章

Java多线程(二)、线程的生命周期和状态控制(转)

Java多线程(二).线程的生命周期和状态控制 分类: javaSE综合知识点 2012-09-10 16:11 15937人阅读 评论(3) 收藏 举报 一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态(runnable). 注意:不能对已经启动的线程再次调用start()方法,否则会出现java.lang.IllegalThreadSt

Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)

一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会引起此共享资源的不一致性.因此,为避免线程安全问题,应该避免多线程环境下对此共享资源的并发访问. 线程安全问题多是由全局变量和静态变量引起的,当多个线程对共享数据只执行读操作,不执行写操作时,一般是线程安全的:当多个线程都执行写操作时,需要考虑线程同步来解决线程安全问题. 二.线程同步(synchr

Java多线程感悟二

写在前面 这篇是Java多线程感悟的第二篇博客,主要讲述的JAVA层面对并发的一些支持.第一篇博客地址为:http://zhangfengzhe.blog.51cto.com/8855103/1607712  下一篇博客将介绍线程池和一些同步工具类. 目录 9.  并发内存模型及并发问题概述 10. volatile和synchronized原理分析 11. ThreadLocal原理及其在Struts/Spring中的应用 12. Atomic 13. Lock 并发内存模型及并发问题概述 首

java多线程系列(二)

对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解能让知识更加简单易懂. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量的并发访问 java多线程系列(三)之等待通知机制 java多线程系列(四)之ReentrantLock的使用 线程安全 线程安全就是多线程访问时,采用了加锁机制,当一个

Java多线程(二)

本文承接上一篇文章<Java多线程(一)>. 四.Java多线程的阻塞状态与线程控制 上文已经提到Java阻塞的几种具体类型.下面分别看下引起Java线程阻塞的主要方法. 1.join() join -- 让一个线程等待另一个线程完成才继续执行.如A线程线程执行体中调用B线程的join()方法,则A线程被阻塞,知道B线程执行完为止,A才能得以继续执行. 1 public class ThreadTest { 2 3 public static void main(String[] args)

Java总结篇系列:Java多线程(二)

四.Java多线程的阻塞状态与线程控制 上文已经提到Java阻塞的几种具体类型.下面分别看下引起Java线程阻塞的主要方法. 1.join() join -- 让一个线程等待另一个线程完成才继续执行.如A线程线程执行体中调用B线程的join()方法,则A线程被阻塞,知道B线程执行完为止,A才能得以继续执行. 1 public class ThreadTest { 2 3 public static void main(String[] args) { 4 5 MyRunnable myRunna

【搞懂Java多线程之二】多线程调度及守护进程

在前一篇文章中说到,所有处在就绪状态中的线程,操作系统会选择优先级最高的优先进行调度,那么是不是优先级高的线程就一定比优先级低的线程先执行呢?线程的优先级又是怎么划分的呢?这篇文章,楼楼就要来说说这个问题啦!欢迎关注我的个人博客主页www.anycodex.com 1.线程的优先级 在Java中,线程优先级的范围为0-10,整数值越大,说明优先级更高. 几个相关的宏定义: MAX_PRIORITY 10,最高优先级 MIN_PRIORITY 1,最低优先级 NORM_PRIORITY 5,默认优

java多线程解读二(内存篇)

线程的内存结构图 一.主内存与工作内存 1.Java内存模型的主要目标是定义程序中各个变量的访问规则.此处的变量与Java编程时所说的变量不一样,指包括了实例字段.静态字段和构成数组对象的元素,但是不包括局部变量与方法参数,因为它们是线程私有的,不会被共享. 2.Java内存模型中规定了所有的变量都存储在主内存中,每条线程还有自己的虚拟内存.线程的虚拟内存中保存了该线程使用到的变量到主内存副本拷贝.线程对变量的所有操作(读取.赋值)都必须在自己的虚拟内存中进行,而不能直接读写主内存中的变量.不同

java多线程(二)锁对象

转载请注明出处:http://blog.csdn.net/xingjiarong/article/details/47679007 在上一篇博客中,我们讨论了Race Condition现象以及它产生的原因,现在我们知道它是不好的一种现象了,那么我们有什么方法避免它呢.最直接有效的方式就是放弃多线程,直接改为使用单线程但操作数据,但是这是不优雅的,因为我们知道有时候,多线程有它自己的优势.在这里我们讨论两种其他的方法--锁对象和条件对象. 锁对象 java SE5.0之后为实现多线程的互斥引入了