0 0

java并发,操作i++,一个诡异的问题!3

源代码

public class Test {

    public static void main(String[] args) {

        final TestRun run = new TestRun();

        Thread thread = new Thread(run);
        Thread thread2 = new Thread(run);
        thread.start();
        thread2.start();

    }
}

class TestRun implements Runnable {

    public Integer i    = 0;
    public Object  lock = new Object();

    @Override
    public void run() {
        synchronized (i) {
            i++;
            System.out.println("step1:" + i);
            i++;
            System.out.println("step2:" + i);
        }
    }
}


运行的结果。按理说,锁住了i对象,同步快中的内容顺序执行,结果为:
step1:1
step2:2
step1:3
step2:4

但结果却是:
step1:1
step1:2
step2:3
step2:4
或者
step1:1
step2:3
step1:2
step2:4

貌似没有锁住。
当改为synchronized (lock){
       ……
}
结果就正常了!


为什么????锁住对象了,不能对对象进行操作吗?

问题补充:
liuqing_2010_07 写道
加锁失败。

不明白,详细解释下?好吗?
2012年4月04日 18:42

3个答案 按时间排序 按投票排序

0 0

采纳的答案

原因是Java的自动封箱和解箱操作在作怪。
这里的i++实际上是i = new Integer(i+1),所以执行完i++后,i已经不是原来的对象了,同步块自然就无效了。
其它基本类型的封装类,如Short、Long等等也不能作为同步对象

2012年4月05日 05:22
0 0

小哀同学 已经道出天机。通过反编译代码来看这个问题。

// Decompiled by DJ v2.9.9.60 Copyright 2000 Atanas Neshkov  Date: 2012-4-5 13:09:35
// Home Page : http://members.fortunecity.com/neshkov/dj.html  - Check often for new version!
// Decompiler options: packimports(3) 
// Source File Name:   Airplane.java

package test;

import java.io.PrintStream;

class TestRun
    implements Runnable
{

    TestRun()
    {
        i = Integer.valueOf(0);
        lock = new Object();
    }

    public void run()
    {
        synchronized(i)
        {
            i = Integer.valueOf(i.intValue() + 1);
            System.out.println((new StringBuilder("step1:")).append(i).toString());
            i = Integer.valueOf(i.intValue() + 1);
            System.out.println((new StringBuilder("step2:")).append(i).toString());
        }
    }

    public Integer i;
    public Object lock;
}


i = Integer.valueOf(i.intValue() + 1);

在这里i已经变为新的对象。所以当线程2进入时临界区的对象i为新的没有加锁的对。
所以线程2能够闯入。加锁失败。在这里这种加锁方法本身就是不好的。直接用lock就行了。你可以
Integer ii = new Integer (0);
synchronized(i)

像上面那样也是没有问题的。
你遇到的这种现象属于“临界区资源泄漏”。

2012年4月05日 13:22
0 0

加锁失败。

2012年4月04日 20:44

相关推荐

    Java面试专题-面试人员必看-微服务架构面试专题系列:Tomcat+Mysql+设计模式+并发+Netty+JVM.rar

    5. **Netty**:Netty是一个高性能的异步事件驱动的网络应用程序框架,常用于创建高效的服务器和客户端。了解Netty的Channel、EventLoop、ByteBuf等核心概念,以及其非阻塞I/O模型。同时,理解Netty如何处理HTTP、...

    Java并发.pdf

    ### Java并发知识点详解 ...综上所述,Java并发编程涉及到诸多复杂因素,包括线程的创建与管理、数据的一致性问题以及Java内存模型的细节等。理解这些概念是实现高性能、高可靠性的多线程应用的基础。

    从volatile说到i++的线程安全问题.docx

    i++操作是一个典型的非原子操作,它包括三个步骤:读取、修改、写回。在多线程环境下,如果多个线程同时执行i++操作,可能会导致结果不正确。 例如,使用一个线程i++,另一个线程i–and,最后得到的结果可能不为0。...

    Java并发编程实践源码

    《Java并发编程实践》是一本深入探讨Java多线程与并发编程的经典著作,其源码提供了丰富的示例,帮助读者理解和应用并发编程的核心概念。在这些文件中,我们可以看到多种并发设计模式和策略的实际运用,下面将逐一...

    java并发编程技术

    5. **非阻塞I/O(NIO)**:NIO(New Input/Output)提供了一种不同于传统阻塞I/O模型的机制,允许程序在数据准备就绪时才进行读写操作,提高了高并发I/O性能。Java NIO库包括Selector(选择器)、Channel(通道)和...

    java并发实战编程 英文版

    《Java并发实战编程》是一本深入探讨Java多线程编程技术的专业书籍,旨在帮助开发者理解和掌握并发编程的核心概念和最佳实践。并发编程是现代软件开发中的关键领域,尤其是在多核处理器普及的今天,利用线程并行执行...

    java并发编程分享

    Java并发编程是Java开发中的重要领域,它涉及到多线程、同步机制、线程池以及并发集合等核心概念。在Java中,并发编程是提高系统性能和资源利用率的关键技术,尤其是在处理大量I/O操作或者计算密集型任务时。本文将...

    java并发工具类

    Java并发工具类是Java平台提供的一系列用于处理多线程并发问题的类和接口,它们在`java.util.concurrent`包中。并发问题主要包括资源竞争、死锁、活锁以及饥饿等,合理使用并发工具可以有效地提高程序的并发性能并...

    Java并发编程:volatile关键字解析

    3. **有序性问题**(Happens-Before原则):这是关于程序执行顺序的概念,即一个操作的执行结果是否对另一个操作可见,以及能否确保这两个操作发生的相对顺序。在并发程序中,如果不能保证操作的顺序,那么可能会...

    多核与并发数据结构-用于列车售票的可线性化并发数据结构+JAVA源码+文档说明

    线性化(Linearizability)是指在并发环境中,对数据结构的操作表现为似乎有一个全局的顺序,尽管实际上操作可能在不同的处理器核心上并行执行。这种特性使得并发数据结构的设计和实现非常复杂,但同时也是提升系统...

    java并发编程实践的.pptx

    - **程序次序法则**:如果一个操作在另一个操作之前发生,那么第一个操作的结果对第二个操作来说是可见的。 - **监视器法则**:解锁监视器的操作发生在随后对该监视器的锁定之前。 - **volatile变量法则**:对...

    java并发编程 英文版

    《Java并发编程英文版》是Doug Lea所著的一部关于Java并发编程的经典作品。Doug Lea是计算机科学领域的知名学者,尤其在并发编程、设计模式、软件工程等领域有深入的研究和独到的见解。本书在1996年首次出版,至今仍...

    基于java+testng+数据库的接口自动化测试.zip

    在接口自动化测试领域,Java、TestNG和数据库的结合是一个常用且强大的组合。这个压缩包“基于java+testng+数据库的接口自动化测试.zip”很可能包含了一套完整的接口自动化测试框架,用于验证后端服务的功能性和数据...

    java并发编程和网络高级编程pdf

    以下将详细讨论《JAVA并发编程实践》和《Java网络高级编程》两本书中涵盖的关键知识点。 首先,让我们关注并发编程。并发编程是现代多核处理器系统中不可或缺的一部分,它允许程序同时执行多个任务,从而提高系统...

    java并发整理

    Java并发是指在一个程序中同时运行多个线程的能力。每个Java程序至少包含一个线程,即启动时运行在`main`方法中的主线程。此外,在Java虚拟机(JVM)初始化过程中还会启动其他后台线程,这些线程的数量和类型取决于...

    技术分享-JAVA并发库解读

    通过对Java并发库的解读,我们可以了解到Java为解决多线程环境下出现的各种问题提供了一系列工具和技术。从重排序的概念出发,我们探讨了如何使用`volatile`关键字以及`final`域来确保多线程程序的一致性和可见性。...

    Java并发编程与高并发解决方案-学习笔记

    ### Java并发编程与高并发解决方案知识点总结 #### 一、并发与高并发基本概念 ##### 1.1 并发 - **定义**: 指一个程序在同一时刻拥有两个或更多的线程,这些线程可以在单核或多核处理器上运行。 - **单核处理器上...

    java selector 测试并发

    JavaSelector在Java NIO(非阻塞I/O)中扮演着关键角色,它允许程序同时监控多个通道(channels)的事件,例如连接请求、数据可用性或者关闭事件,而无需在一个单独的线程中轮询所有通道。这种机制极大地提高了处理...

Global site tag (gtag.js) - Google Analytics