`

volatile、synchronized示例

 
阅读更多

 

1、synchronized保证同步

先看一个生成偶数的类
[java] view plaincopy

    <span style="font-size:16px;">package demo.thread; 
     
    /**
     *这是一个int生成器的抽象类
     * 
     */ 
    public abstract class IntGenerator { 
         
        private volatile boolean canceled = false; 
     
        public abstract int next(); 
     
        public void cancel() { 
            canceled = true; 
        } 
     
        public boolean isCanceled() { 
            return canceled; 
        } 
    } 
    </span> 


 
[java] view plaincopy

    <span style="font-size:16px;">/*
     * 产生偶数
     */ 
    class EvenGenerator extends IntGenerator { 
        private int currentEvenValue = 0; 
        String s = ""; 
     
        @Override 
        public int next() { 
            <span style="color:#ff0000;">synchronized </span>(s) { 
                ++currentEvenValue; 
                ++currentEvenValue; 
                return currentEvenValue; 
            } 
        } 
     
    //  //这样也可以 
    //  public <span style="color:#ff0000;">synchronized </span>int next() { 
    //          ++currentEvenValue; 
    //          ++currentEvenValue; 
    //          return currentEvenValue; 
    //  } 
    }</span> 


注意到在产生偶数是要加同步锁,否则可能线程1刚好执行了一句++currentEvenValue;操作,就被线程2抢去了cpu,此时线程2执行return currentEvenValue;这时返回的就是一个奇数。加synchronized 就是两个线程同时只能一个线程执行synchronized 块的代码。

测试代码:
[java] view plaincopy

    <span style="font-size:16px;">package demo.thread; 
     
    import java.util.concurrent.ExecutorService; 
    import java.util.concurrent.Executors; 
     
    /*
     * 消费数字
     */ 
    public class EvenChecker implements Runnable { 
         
        private IntGenerator generator; 
        private final int id; 
     
        public EvenChecker(IntGenerator g, int ident) { 
            generator = g; 
            id = ident; 
        } 
     
        public void run() { 
            while (!generator.isCanceled()) { 
                int val = generator.next(); 
                if (val % 2 != 0) {//如果不是偶数 
                    System.out.println(val + " not enen!"); 
                    generator.cancel(); 
                } 
            } 
        } 
     
        public static void test(IntGenerator gp, int count) { 
            ExecutorService exec = Executors.newCachedThreadPool(); 
            for (int i = 0; i < count; i++) 
                exec.execute(new EvenChecker(gp, i)); 
            exec.shutdown(); 
        } 
     
        public static void test(IntGenerator gp) { 
            test(gp, 10); 
        } 
     
        public static void main(String[] args) { 
            test(new EvenGenerator()); 
        } 
    }</span> 


分析:如果产生偶数的类未加synchronized,那么测试程序将会出现奇数导致退出程序。

 

2、volatile表示原子性,可见性。

      对于多个线程之间共享的变量,每个线程都有自己的一份拷贝,当线程1改变变量值时,其他线程并不马上知道该变量值改变了,volatile就保证了变量值对各个线程可见,一个线程改变该值,马上其他线程中该值也改变。原子性表明操作不可中断,如基本变量赋值。

     代码示例:
[java] view plaincopy

    <span style="font-size:16px;">package demo.thread; 
     
    public class VolatileDemo implements Runnable { 
         
        private volatile int i = 0;//volatile设置可见性 
     
        public synchronized  int getValue() { 
            return i; 
        } 
     
        private synchronized void enenIncrement() { 
            i++; 
            i++; 
        } 
     
        @Override 
        public void run() { 
            while (true) 
                enenIncrement(); 
        } 
     
        public static void main(String[] args) { 
            VolatileDemo at = new VolatileDemo(); 
            new Thread(at).start(); 
            while (true) { 
                int val = at.getValue(); 
                if (val % 2 != 0) {//出现奇数,退出程序 
                    System.out.println(val+" is not enen!"); 
                    System.exit(0); 
                } 
            } 
     
        } 
    } 
    </span> 


注意i++操作并不是原子行操作,getValue() 方法也要加synchronized 。

分享到:
评论

相关推荐

    java同步synchronized关键字用法示例

    因此,`volatile`通常用于读多写少的情况,而`synchronized`适用于读写都频繁的场景。 **4. synchronized的局限性和改进** `synchronized`虽然提供了线程安全,但它会带来一定的性能开销。在Java 5之后,引入了`...

    并发编程一之synchronized和volatile.rar

    本资源"并发编程一之synchronized和volatile.rar"提供了多个示例代码(demo1到demo12),帮助我们深入理解这两个关键字的功能与用法。 1. **synchronized关键字**: - **互斥性**:synchronized可以确保同一时间...

    java多线程中的volatile和synchronized用法分析

    在上述示例中,`count`被声明为volatile,这使得每个线程在执行`count++`操作时,都能看到最新的count值。然而,volatile并不保证原子性,因此在多个线程同时执行`count++`时,可能出现线程交错执行,导致最终结果...

    volatile用法

    `volatile`和`synchronized`都是Java中的关键字,虽然它们都可以用于处理多线程同步问题,但作用机制不同。`volatile`确保了变量的修改对于其他线程是可见的,而`synchronized`则提供了互斥访问,保证同一时间只有...

    volatile 变量的说明

    例如,如果你有一个计数器并尝试通过多个线程同时递增,volatile并不能保证递增操作的原子性,因此仍然需要使用synchronized或者其他并发控制机制来保证。 下面是一些关于volatile的常见问题及其解答: 1. **参数...

    java synchronized demo

    本示例"java synchronized demo"旨在探讨`synchronized`关键字的用法及其作用机制。下面将详细阐述`synchronized`的相关知识点。 1. **synchronized的作用**: - `synchronized`关键字主要用于解决多线程环境中的...

    [JAVA][synchronized的使用]

    - **volatile**:相比`synchronized`,`volatile`关键字轻量级且快速,但只适用于变量的读写操作,无法保证复合操作的原子性。 - **ReentrantLock**:是Java并发包`java.util.concurrent.locks`中的可重入锁,提供...

    Synchronized 终极说明教程

    在实际开发中,我们可以通过编写测试示例来验证`synchronized`的效果。例如,我们可以创建两个线程,一个线程负责加一操作,另一个线程负责减一操作,通过`synchronized`控制并发执行的顺序,确保结果的正确性。 五...

    Java线程之线程同步synchronized和volatile详解

    Java线程之线程同步synchronized和volatile详解 Java线程同步是Java多线程编程中非常重要的一个方面,主要涉及到线程安全、可见性和有序性三个方面。Java提供了多种同步机制来解决线程安全问题,包括synchronized和...

    Java并发volatile关键字.docx

    在上述示例中,`Conter.inc()`方法中的`count++`操作,即使count是volatile的,也无法保证线程安全,因为不同线程可能同时进行读取、增加和写回,导致结果不一致。 为了确保原子性,可以使用`synchronized`块或Java...

    一文精通Java中的volatile关键字

    在上述示例中,如果没有使用`volatile`,线程B可能无法观察到线程A对`flag`的更新,因为它可能会使用自己本地内存中的旧值。而使用`volatile`后,线程B会直接从主内存中读取最新值,从而避免了这种问题。 2. 指令重...

    Java并发编程系列- synchronized

    在给定的示例中,`synchronized`被用来修饰实例方法`increase()`。由于`i`是静态变量,属于类级别的共享资源,两个线程`t1`和`t2`分别启动并调用`increase()`方法。如果没有`synchronized`,由于`i++`操作不是原子性...

    java入门教程:数据类型_Java理论与实践如何正确使用Volatile变量.docx

    相比于传统的锁机制如`synchronized`,`volatile`变量的使用更为简单、高效,但在适用场景上存在一定的局限性。本文旨在详细介绍`volatile`变量的基本概念、使用场景以及潜在的限制。 #### Volatile变量的概念 `...

    volatile相关理论知识

    这意味着volatile变量的读写操作不会被其他操作插队,避免了指令重排序带来的问题,但仍然不能代替synchronized关键字来实现线程安全的复杂操作。 总结来说,volatile关键字在Java中是解决多线程并发问题的重要工具...

    解开Volatile的面纱V1.1

    通过对比`VolatileDemo`和`NonVolatileDemo`两个示例,我们可以看到`volatile`关键字在多线程环境中的重要性。在`VolatileDemo`中,由于`stop`变量被标记为`volatile`,因此子线程在主线程修改`stop`为`true`后能...

    Java中Volatile关键字详解及代码示例

    Java中Volatile关键字详解及代码示例 一、基本概念 在Java中,Volatile关键字是一个非常重要的概念,它与Java内存模型中的可见性、原子性和有序性息息相关。可见性是指线程之间的可见性,一个线程修改的状态对另一...

    Java并发编程(18)第五篇中volatile意外问题的

    在文档中,作者可能通过一个示例代码展示了volatile无法解决的并发问题,比如一个典型的计数器场景。如果使用volatile修饰一个共享的计数器变量`count`,并有多个线程同时进行加一操作,由于这些操作不是原子的,...

    16 让你眼见为实—volatile详解.pdf

    在代码示例中,主线程修改了volatile变量flag,这将确保所有线程都能看到这个变化,从而触发相应的动作。如果没有volatile修饰,线程可能从本地缓存读取旧的变量值,导致无法感知到变化。这是因为CPU的缓存优化策略...

    tuling-juc-final.zip

    本项目"tuling-juc-final.zip"显然聚焦于Java并发编程的实践,通过一系列代码示例来演示和解释Java内存模型(JMM)、`synchronized`关键字以及`volatile`关键字的使用。下面我们将深入探讨这些核心概念。 Java内存...

    【并发编程】volatile的原理我好像又懂了.pdf

    - **未加 `volatile` 的示例**:在没有使用 `volatile` 修饰的情况下,其他线程可能因为缓存不一致而无法及时看到变量的变化。 - **加上 `volatile` 的示例**:通过使用 `volatile` 修饰符,可以确保其他线程能够...

Global site tag (gtag.js) - Google Analytics