为什么会有线程同步的概念呢?为什么要同步?什么是线程同步?先看一段代码:

package com.maso.test;

public class ThreadTest2 implements Runnable{
private TestObj testObj = new TestObj(); public static void main(String[] args) {
ThreadTest2 tt = new ThreadTest2();
Thread t1 = new Thread(tt, "thread_1");
Thread t2 = new Thread(tt, "thread_2");
t1.start();
t2.start();
} @Override
public void run() { for(int j = 0; j < 10; j++){
int i = fix(1);
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println(Thread.currentThread().getName() + " : i = " + i);
} } public int fix(int y){
return testObj.fix(y);
} public class TestObj{
int x = 10; public int fix(int y){
return x = x - y;
}
} }

输出结果后,就会发现变量x被两个线程同一时候操作。这样就非常easy导致误操作。

怎样才干解决问题呢?用线程的同步技术。加上synchronizedkeyword

	public synchronized int fix(int y){
return testObj.fix(y);
}

加上同步后,就能够看到有序的从9输出到-10.

假设加到TestObj类的fix方法上能不能实现同步呢?

	public class TestObj{
int x = 10; public synchronized int fix(int y){
return x = x - y;
}
}

假设将synchronized加到方法上则等价于

	synchronized(this){

	}

能够推断出两个线程使用的TestObj类的同一个实例testOjb,所以后实现同步,可是输出的结果却不是理想的结果。这是由于当A线程运行完x = x - y后还没有输出则B线程已经进入開始运行x = x - y.

所以像以下这样输出就不会有什么问题了:

	public class TestObj{
public TestObj(){
System.out.println("调用了构造函数");
} int x = 10; public synchronized int fix(int y){
x = x - y;
System.out.println(Thread.currentThread().getName() + " : x = " + x);
return x;
}
}

假设将外部的fix方法改动例如以下:

	public int fix(int y){
ax++ ;
if(ax%2 == 0){
return testObj.fix(y, testObj.str1);
}else{
return testObj.fix(y, testObj.str2);
}
}
	public class TestObj{
String str1 = "a1";
String str2 = "a2"; public TestObj(){
System.out.println("调用了构造函数");
} int x = 10; public int fix(int y, String str){
synchronized (str) {
x = x - y;
System.out.println(Thread.currentThread().getName() + " : x = " + x);
}
return x;
}
}

此时synchronized中的str对象不是同一个对象,所以两个线程所持有的对象锁不是同一个,这样就不能实现同步。

要实现线程之间的相互排斥就要使用同一个对象锁。

什么是死锁呢?举个样例就是比方你和同学租了个两室的房子,你拿着你房子的钥匙。你同学拿着他房子的钥匙,如今你在房子等你同学将他的钥匙给你然后你进他房子。你同学在他的房子等你将钥匙给他然后他进你的房子,这样就死锁了。

package com.maso.test;

public class ThreadDieSock implements Runnable {
private int flag = 1;
private Object obj1 = new Object(), obj2 = new Object(); public void run() {
System.out.println("flag=" + flag);
if (flag == 1) {
synchronized (obj1) {
System.out.println("我已经锁定obj1,歇息0.5秒后锁定obj2去!");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj2) {
System.out.println("1");
}
}
}
if (flag == 0) {
synchronized (obj2) {
System.out.println("我已经锁定obj2,歇息0.5秒后锁定obj1去。");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj1) {
System.out.println("0");
}
}
}
} public static void main(String[] args) {
ThreadDieSock run01 = new ThreadDieSock();
ThreadDieSock run02 = new ThreadDieSock();
run01.flag = 1;
run02.flag = 0;
Thread thread01 = new Thread(run01);
Thread thread02 = new Thread(run02);
System.out.println("线程開始喽! ");
thread01.start();
thread02.start();
}
}

最新文章

  1. php使用post动态选择头像和js事件动态改变头像
  2. ArcGIS Add-in插件开发从0到1及实际案例分享
  3. 用JQuery Validate框架,在IE8下验证报错问题解决
  4. Python 字符串分割的方法
  5. tomcat7.0配置CORS(跨域资源共享)
  6. MongoDB的数据库基本操作(二)
  7. Android+Sqlite 实现古诗阅读应用(一)
  8. iOS网络开发之AFNetworking
  9. [php]使用会话session
  10. Android 可拖动列表项的ListView
  11. php安装redis扩展
  12. Python新手学习基础之函数-全局变量和局部变量
  13. XML实例文档
  14. Cocos2d-x3.0 文件处理
  15. 聊聊ThreadLocal原理以及使用场景-JAVA 8源码
  16. IE7、IE8不兼容js trim函数的解决方法
  17. 使用iconfont图标
  18. VS2017 安装打包插件
  19. Structured Streaming编程向导
  20. 编译Android VNC Server

热门文章

  1. 【数据分析 R语言实战】学习笔记 第四章 数据的图形描述
  2. [翻译] API测试最佳实践 - 组织你的测试
  3. C#中的常量、类型推断和作用域
  4. echarts 外观效果修改
  5. 模块 (Module)
  6. (转)淘淘商城系列——引用dubbo服务
  7. CAD参数绘制文字(网页版)
  8. print reverse &lt;&gt; 是打印全部的文件内容 ?
  9. PyQt5实现第一个桌面应用程序
  10. pytorch之Tensor与Variable的区别