synchronized同步锁的问题

DM_xianzhushou 2017-09-25 12:34:12
在网上学习了synchronized相关的知识后,想亲自动手验证下,但出现的情况,让人一脸懵逼!
吊大的,帮忙看下,代码很简单

public class SyncThread implements Runnable {


public synchronized void run() {
for (int i = 0; i < 5; i ++) {
try {
System.out.println(Thread.currentThread().getName() + ":" +i);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

测试方法
public class SyncThreadTest {

@Test
public void test1(){
SyncThread syncThread0 = new SyncThread();
SyncThread syncThread1 = new SyncThread();
Thread thread0 = new Thread(syncThread0, "SyncThread0");
Thread thread1 = new Thread(syncThread1, "SyncThread1");
thread1.start();
thread2.start();
}
}


按照预期(教程)输出:
SyncThread0:0
SyncThread0:1
SyncThread0:2
SyncThread0:3
SyncThread0:4
SyncThread1:5
SyncThread1:6
SyncThread1:7
SyncThread1:8
SyncThread1:9


实际输出:


多次运行测试方法:


先谢谢各位大吊
...全文
424 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
DM_xianzhushou 2017-09-27
  • 打赏
  • 举报
回复
引用 6 楼 sanjuejianke 的回复:
看你的输出日志,你的开发工具是通过socket去连接java虚拟机,然后获取到虚拟机的输出信息,打印在控制台,然后在第一次线程sleep的时候,socket就断开了,然后你就看不到日志输出了。我觉得其实程序还是在虚拟机上正常跑的。你可以测试一下,日志不要直接System.out.print打印,而是输出到一个文件中去。执行完了你可以看看文件中的日志信息。如果是这样的话,这肯定是你的开发工具的设置问题,可以从这点找下问题。


按照6搂说的修改了下代码

public class SyncThread implements Runnable {


public synchronized void run() {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 5; i ++) {
try {
stringBuffer.append(Thread.currentThread().getName());
stringBuffer.append(":");
stringBuffer.append(i);
stringBuffer.append(System.getProperty("line.separator"));

Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
File file = new File("C:\\Users\\thinkpad\\Desktop\\test.txt");
try {
FileWriter writer = new FileWriter(file,true);
writer.write(stringBuffer.toString());
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
}

}

}


输出结果:


最终结论,达到预期效果,原因正如六楼所说,程序还是在虚拟机上正常跑的.
本人用的idea,然后切换eclipse也是一样.正在尝试如何更改配置.

多谢各位的回答
愤怒的502 2017-09-26
  • 打赏
  • 举报
回复
public class SyncThreadTest { @Test public void test1(){ SyncThread syncThread0 = new SyncThread(); SyncThread syncThread1 = new SyncThread(); Thread thread0 = new Thread(syncThread0, "SyncThread0"); Thread thread1 = new Thread(syncThread1, "SyncThread1"); thread1.start(); thread2.start(); } } 上面这个方法,syncThread0 和syncThread1是两个对象,调用run方法的时候,锁住的是this,并不会出现阻塞的情况。 public static void main(String[] args) { SyncThread syncThread0 = new SyncThread(); // SyncThread syncThread1 = new SyncThread(); Thread thread0 = new Thread(syncThread0, "SyncThread0"); Thread thread1 = new Thread(syncThread0, "SyncThread1"); thread0.start(); thread1.start(); } 而这一个,syncThread0 ,两个线程共用syncThread0,thread0调用run的时候,将会获得syncThread0的锁,thread1调用之前必须等待thread0释放syncThread0才行
黄卷青灯957 2017-09-26
  • 打赏
  • 举报
回复
你通过实现runable对象实现的线程new SyncThread()实际只是一个线程执行的target而并非是一个实际的线程 而你的在调用线程时 Thread thread0 = new Thread(syncThread0, "SyncThread0"); Thread thread1 = new Thread(syncThread1, "SyncThread1"); 实际两个线程对象thread0与thread1执行的target的对象并不相同不是同一个SyncThrea 所以两个线程执行体中的for 循环的i完全不是同一个 正确做法 Thread thread0 = new Thread(syncThread0, "SyncThread0"); Thread thread1 = new Thread(syncThread0, "SyncThread0"); 使用同一个target 实现两个线程共享一个i,实现你所想要的效果 希望看完能明白
sjjk 2017-09-26
  • 打赏
  • 举报
回复
看你的输出日志,你的开发工具是通过socket去连接java虚拟机,然后获取到虚拟机的输出信息,打印在控制台,然后在第一次线程sleep的时候,socket就断开了,然后你就看不到日志输出了。我觉得其实程序还是在虚拟机上正常跑的。你可以测试一下,日志不要直接System.out.print打印,而是输出到一个文件中去。执行完了你可以看看文件中的日志信息。如果是这样的话,这肯定是你的开发工具的设置问题,可以从这点找下问题。
DM_xianzhushou 2017-09-25
  • 打赏
  • 举报
回复
谢谢各位的回答,1搂的说法,我之前是有运行过的,然后在测试一次,也是这种情况



不知道1楼是否在自己的环境运行过,确实是如此结果,这样的话可能是环境问题了,我的是JDK1.8,但我更倾向与是阻塞了,但我对这方面了解不深,不敢妄断
休谱诺斯 2017-09-25
  • 打赏
  • 举报
回复
1楼说的没问题
thatsinteresting 2017-09-25
  • 打赏
  • 举报
回复
按照你给出的代码并不能德道预期的结果。

SyncThread syncThread0 = new SyncThread();
SyncThread syncThread1 = new SyncThread();
Thread thread0 = new Thread(syncThread0, "SyncThread0");
Thread thread1 = new Thread(syncThread1, "SyncThread1");
thread0.start();
thread1.start();
thread0和thread1分别对应了syncThread0和syncThread1两个实例, 这两个线程完全独立的,运行时并不是进入同一个run方法。 运行结果:

SyncThread0:0
SyncThread1:0
SyncThread0:1
SyncThread1:1
SyncThread0:2
SyncThread1:2
SyncThread0:3
SyncThread1:3
SyncThread0:4
SyncThread1:4
只用一个SyncThread实例:

    public static void main(String[] args) {

    SyncThread syncThread0 = new SyncThread();
//    SyncThread syncThread1 = new SyncThread();
    Thread thread0 = new Thread(syncThread0, "SyncThread0");
    Thread thread1 = new Thread(syncThread0, "SyncThread1");
    thread0.start();
    thread1.start();
    }
运行结果:

SyncThread1:0
SyncThread1:1
SyncThread1:2
SyncThread1:3
SyncThread1:4
SyncThread0:0
SyncThread0:1
SyncThread0:2
SyncThread0:3
SyncThread0:4

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧