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 。
相关推荐
因此,`volatile`通常用于读多写少的情况,而`synchronized`适用于读写都频繁的场景。 **4. synchronized的局限性和改进** `synchronized`虽然提供了线程安全,但它会带来一定的性能开销。在Java 5之后,引入了`...
本资源"并发编程一之synchronized和volatile.rar"提供了多个示例代码(demo1到demo12),帮助我们深入理解这两个关键字的功能与用法。 1. **synchronized关键字**: - **互斥性**:synchronized可以确保同一时间...
在上述示例中,`count`被声明为volatile,这使得每个线程在执行`count++`操作时,都能看到最新的count值。然而,volatile并不保证原子性,因此在多个线程同时执行`count++`时,可能出现线程交错执行,导致最终结果...
`volatile`和`synchronized`都是Java中的关键字,虽然它们都可以用于处理多线程同步问题,但作用机制不同。`volatile`确保了变量的修改对于其他线程是可见的,而`synchronized`则提供了互斥访问,保证同一时间只有...
例如,如果你有一个计数器并尝试通过多个线程同时递增,volatile并不能保证递增操作的原子性,因此仍然需要使用synchronized或者其他并发控制机制来保证。 下面是一些关于volatile的常见问题及其解答: 1. **参数...
本示例"java synchronized demo"旨在探讨`synchronized`关键字的用法及其作用机制。下面将详细阐述`synchronized`的相关知识点。 1. **synchronized的作用**: - `synchronized`关键字主要用于解决多线程环境中的...
- **volatile**:相比`synchronized`,`volatile`关键字轻量级且快速,但只适用于变量的读写操作,无法保证复合操作的原子性。 - **ReentrantLock**:是Java并发包`java.util.concurrent.locks`中的可重入锁,提供...
在实际开发中,我们可以通过编写测试示例来验证`synchronized`的效果。例如,我们可以创建两个线程,一个线程负责加一操作,另一个线程负责减一操作,通过`synchronized`控制并发执行的顺序,确保结果的正确性。 五...
Java线程之线程同步synchronized和volatile详解 Java线程同步是Java多线程编程中非常重要的一个方面,主要涉及到线程安全、可见性和有序性三个方面。Java提供了多种同步机制来解决线程安全问题,包括synchronized和...
在上述示例中,`Conter.inc()`方法中的`count++`操作,即使count是volatile的,也无法保证线程安全,因为不同线程可能同时进行读取、增加和写回,导致结果不一致。 为了确保原子性,可以使用`synchronized`块或Java...
在上述示例中,如果没有使用`volatile`,线程B可能无法观察到线程A对`flag`的更新,因为它可能会使用自己本地内存中的旧值。而使用`volatile`后,线程B会直接从主内存中读取最新值,从而避免了这种问题。 2. 指令重...
在给定的示例中,`synchronized`被用来修饰实例方法`increase()`。由于`i`是静态变量,属于类级别的共享资源,两个线程`t1`和`t2`分别启动并调用`increase()`方法。如果没有`synchronized`,由于`i++`操作不是原子性...
相比于传统的锁机制如`synchronized`,`volatile`变量的使用更为简单、高效,但在适用场景上存在一定的局限性。本文旨在详细介绍`volatile`变量的基本概念、使用场景以及潜在的限制。 #### Volatile变量的概念 `...
这意味着volatile变量的读写操作不会被其他操作插队,避免了指令重排序带来的问题,但仍然不能代替synchronized关键字来实现线程安全的复杂操作。 总结来说,volatile关键字在Java中是解决多线程并发问题的重要工具...
通过对比`VolatileDemo`和`NonVolatileDemo`两个示例,我们可以看到`volatile`关键字在多线程环境中的重要性。在`VolatileDemo`中,由于`stop`变量被标记为`volatile`,因此子线程在主线程修改`stop`为`true`后能...
Java中Volatile关键字详解及代码示例 一、基本概念 在Java中,Volatile关键字是一个非常重要的概念,它与Java内存模型中的可见性、原子性和有序性息息相关。可见性是指线程之间的可见性,一个线程修改的状态对另一...
在文档中,作者可能通过一个示例代码展示了volatile无法解决的并发问题,比如一个典型的计数器场景。如果使用volatile修饰一个共享的计数器变量`count`,并有多个线程同时进行加一操作,由于这些操作不是原子的,...
在代码示例中,主线程修改了volatile变量flag,这将确保所有线程都能看到这个变化,从而触发相应的动作。如果没有volatile修饰,线程可能从本地缓存读取旧的变量值,导致无法感知到变化。这是因为CPU的缓存优化策略...
本项目"tuling-juc-final.zip"显然聚焦于Java并发编程的实践,通过一系列代码示例来演示和解释Java内存模型(JMM)、`synchronized`关键字以及`volatile`关键字的使用。下面我们将深入探讨这些核心概念。 Java内存...
- **未加 `volatile` 的示例**:在没有使用 `volatile` 修饰的情况下,其他线程可能因为缓存不一致而无法及时看到变量的变化。 - **加上 `volatile` 的示例**:通过使用 `volatile` 修饰符,可以确保其他线程能够...