0 0

一个j2se同步锁的问题,print语句可以影响同步?10

代码如下:
public class TT implements Runnable {
int b = 100;

public synchronized void m1() throws Exception {
b = 1000;
Thread.sleep(500);

System.out.println("m1.b = " + b);
}

public synchronized void m2() throws Exception {
//public void m2() throws Exception {
Thread.sleep(250);
b = 2000;
//System.out.println("m2.b = " + b);
}

public void run() {
try {m1();}
catch(Exception e) {e.printStackTrace();}
}

public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t1 = new Thread(tt);
t1.start();

tt.m2();

System.out.println("tt.b = " + b);
}
}

这段代码有两处标注,第一个标注地方表示了m2方法是否同步;第二个地方是在m2中是否采用print语句。
运行结果如下:

1. 如果m2不同步,则无论print语句是否执行,结果均为:tt.b=2000  m1.b=2000;(m2.b的我就不写了)

2. 如果m2同步,则在有print语句的时候,结果为:m2.b=2000  tt.b=2000  m1.b=1000

3. 如果m2同步,在没有print语句的时候,结果为: tt.b=1000  m1.b=1000

请为我解释一下上述情况的原因(同步前后的不同也请给解释一下吧,本来搞得挺明白的,现在却迷糊了),谢谢了!
2012年5月19日 00:45

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

0 0

t1.start();
//先说这里吧,这里start之后,t1并没有立刻执行run方法
//导致m2先拿到对象锁,然后m2开始执行,并锁住对象tt,m1此时正在等待m2释放锁
tt.m2();
//执行m2这里没有什么问题,问题在最后一句打印上面
//问题是它到底什么时候释放的 对象锁
//不打印的话,立刻就释放了,这个时候m1就会拿到tt对象,并立刻修改b的值
//打印的话,(打印的本身是一个很复杂的结果)什么时候释放的锁,不好说所以我改造了m2方法

    public synchronized void m2() throws Exception{
        Thread.sleep(1000);
        b = 2000;
       final int temp=b;
      //这里多开一个线程,保证对象锁直接释放
        new Thread(){public void run() {System.out.println("m2.b = "+temp);};}.start();
    
        //System.out.println("m2.b = " + b);
    }


//这里的问题就是主线程和t1线程 是t1先改变b的值,还是sysout先打印b的值
//  如果在这里加上Thread.sleep(100);可以发现
//  结果
//    tt.b = 1000
//    m2.b = 2000
//    m1.b = 1000
System.out.println("tt.b = " + b);

//看了下sysout的源码,发现问题可能不是在这里而是在字符串的拼接这里
//因为java重载了+操作符,jdk1.6将+用StringBuilder 来优化,而StringBuilder 并不是线程安全的,所以可能是这里的问题,将拼接改为线程安全的Stringbuffer来处理字符串拼接问题

 int b = 100;
    StringBuffer sb ;

    public synchronized void m1() throws Exception{
        sb = new StringBuffer();
        b = 1000;
        Thread.sleep(2000);
        System.out.println(sb.append("m1.b = ").append(b));
    }

    public synchronized void m2() throws Exception{
        sb = new StringBuffer();
        Thread.sleep(1000);
        b = 2000;
        System.out.println(sb.append("m2.b = ").append(b));
    }

    public void run()
    {
        try{  m1();}  catch (Exception e){ e.printStackTrace();}
    }

    public static void main(String[] args) throws Exception
    {
        L l = new L();
       Thread t1= new Thread(l);
       t1.start();
        l.m2();
        System.out.println("tt.b = " + l.b);
    }


结果
m2.b = 2000
tt.b = 1000
m1.b = 1000

以上都是我猜想的。。。对不对还要高手来鉴别




2012年5月20日 09:41

相关推荐

    学习j2se的30个问题

    4. **多态性**:指一个类的行为可以通过继承和方法重写来实现动态的变化。这是面向对象编程的一个核心概念。 5. **扩展类**:Java中的类可以被其他类继承,从而复用代码和功能。 6. **抽象类与接口**: - **抽象...

    j2se6中文网页版

    本资源“j2se6中文网页版”显然是一个中文版的J2SE 6 API文档,旨在帮助中国开发者更方便地理解和使用Java编程语言。 1. **Java API**:Java API是Java平台的核心,包含了大量预定义的类库,如集合框架、I/O流、...

    J2SE_API J2SE_API

    J2SE_API、J2SE_API、J2SE_API、J2SE_API、J2SE_API、J2SE_API、J2SE_API

    J2SE基础源代码

    在"J2SE基础源代码"这个主题中,我们可以深入探讨以下几个关键知识点: 1. **Java语法**:Java是一种面向对象的编程语言,它的语法结构严谨,包括类、对象、继承、封装、多态等核心概念。源代码中可能会包含这些...

    j2se1.5中文api

    Java 2 Platform, Standard Edition (J2SE) 1.5,也被称为Java SE 5.0,是Java编程语言的一个重要版本,它引入了大量的新特性和改进,对Java开发者来说具有里程碑式的意义。J2SE 1.5中文API为中国的开发者提供了方便...

    java j2se源码

    马士兵老师的J2SE课程源代码正是围绕这些知识点编写的,每个小例题都对应一个具体的知识点。通过实际操作和分析这些代码,你可以更深入地理解和掌握Java编程技术,从而提升自己的编程能力。这些源代码是你实践和学习...

    j2se全部学习代码

    "j2se全部学习代码"这个标题表明这是一个包含了一系列用于学习J2SE的编程实践项目。描述中提到,这个压缩包包含了从初学者阶段到全面掌握J2SE的学习过程中的所有练习代码,这意味着我们可以期待看到从基础语法到高级...

    java课程设计大作业-用J2SE写的一个坦克大战小游戏

    java课程设计大作业——用J2SE写的一个坦克大战小游戏java课程设计大作业——用J2SE写的一个坦克大战小游戏java课程设计大作业——用J2SE写的一个坦克大战小游戏java课程设计大作业——用J2SE写的一个坦克大战小游戏...

    j2se7官方API

    Java 2 Standard Edition 7(简称J2SE 7或Java 7)是Java平台的一个重要版本,它引入了一系列新特性和改进,旨在提高开发人员的效率和代码的可维护性。官方API文档是理解这些特性和接口的关键资源。下面我们将深入...

    完整的J2SE所有代码

    这个压缩包包含的“完整的J2SE所有代码”显然是一个全面的Java基础学习资源,涵盖了从基本语法到高级特性的各种示例。下面,我们将深入探讨这些知识点。 首先,J2SE的基础部分包括Java编程语言的基本语法,如变量、...

    j2se_中文版

    Java 2 Platform, Standard Edition(J2SE)是Java开发平台的一个重要组成部分,主要用于桌面应用和服务器端开发。中文版的J2SE API文档对于中国开发者来说尤其方便,它提供了全面的API参考,帮助理解并使用Java编程...

    J2SE学习入门教程

    3. **异常处理**:Java中的异常处理机制是一个重要的部分,通过try-catch-finally语句块来捕获和处理运行时可能出现的错误,保证程序的健壮性。 4. **集合框架**:Java集合框架包括接口(如List、Set、Map)和实现...

    J2SE.rar_j2se

    Java Standard Edition(J2SE)是Java开发平台的一个核心组件,主要针对桌面应用和服务器端应用的开发。这个“J2SE.rar_j2se”压缩包包含的是关于J2SE的教程资源,包括视频讲解、PPT演示以及配套的源代码。通过这些...

    j2se代码.zip

    理解类(class)的概念,知道如何定义一个类,包括属性(fields)和方法(methods),是学习 Java 的核心。同时,要学会如何创建对象(实例化)并调用其方法。 3. **封装、继承和多态**:封装是将数据和操作数据的...

    j2se doc 中文版

    这个"J2SE doc 中文版"是一个为中文用户特别准备的文档集合,它提供了详细的 API 参考、教程和指南,帮助开发者深入理解 Java 编程语言和其运行环境。 1. **Java API 参考**:文档中包含了 J2SE 平台上所有类库的...

    j2se练习小程序

    Java 2 Platform, ...每个子文件可能对应一个特定的主题,例如,一个文件可能是关于集合框架的实现,另一个可能是多线程的示例。实践是检验理论的最好方式,希望这个项目能帮助你扎实地掌握Java的J2SE核心知识。

    j2se实现计算器,界面优美

    在本项目中,我们关注的是一个使用Java标准版(J2SE)实现的计算器应用程序。这个计算器项目不仅提供了基本的计算功能,而且它的图形用户界面(GUI)设计得相当优美,使得用户交互体验良好。这对于那些正在学习Java ...

    J2SE基础知识大全

    J2SE基础知识是每一个Java开发者必须掌握的核心技能。以下将详细阐述J2SE中的关键概念和技术。 1. **Java语言基础** - **语法**:包括变量声明、数据类型(基本类型和引用类型)、运算符、流程控制(如if语句、for...

    基于j2se的俄罗斯方块

    本教程将深入讲解如何利用Java的J2SE(Java Standard Edition)平台,结合Eclipse 3.5集成开发环境,来实现一个功能完备的俄罗斯方块游戏。 首先,让我们了解J2SE。J2SE是Java平台的核心部分,提供了编写桌面应用的...

Global site tag (gtag.js) - Google Analytics