相关链接:
【java多线程编程核心技术】1.Java多线程技能-笔记总结
【Java多线程编程核心技术】2.对象及变量的并发访问(上)-笔记总结
【Java多线程编程核心技术】2.对象及变量的并发访问(下)-笔记总结
【Java多线程编程核心技术】3.线程间通信 -笔记总结
【Java多线程编程核心技术】4.Lock的使用-笔记总结
【Java多线程编程核心技术】5.定时器Timer-笔记总结
【Java多线程编程核心技术】6.单例模式与多线程-笔记总结
【Java多线程编程核心技术】7.拾遗增补-笔记总结
synchronized同步方法
方法内的变量为线程安全
“非线程安全”问题存在于“实例变量”中,如果是方法内部的私有变量,则不存在“非线程安全”问题
实例变量非线程安全
package service;
public class HasSelfPrivateNum {
private int num = 0;
// synchronized public void addI(String username) {
public void addI(String username) { //此处未同步,会发生"非线程安全"问题
try {
if (username.equals("a")) {
num = 100;
System.out.println("a set over!");
Thread.sleep(2000);
} else {
num = 200;
System.out.println("b set over!");
}
System.out.println(username + " num=" + num);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package extthread;
import service.HasSelfPrivateNum;
public class ThreadA extends Thread {
private HasSelfPrivateNum numRef;
public ThreadA(HasSelfPrivateNum numRef) {
super();
this.numRef = numRef;
}
@Override
public void run() {
super.run();
numRef.addI("a");
}
}
package extthread;
import service.HasSelfPrivateNum;
public class ThreadB extends Thread {
private HasSelfPrivateNum numRef;
public ThreadB(HasSelfPrivateNum numRef) {
super();
this.numRef = numRef;
}
@Override
public void run() {
super.run();
numRef.addI("b");
}
}
package test;
import service.HasSelfPrivateNum;
import extthread.ThreadA;
import extthread.ThreadB;
public class Run {
public static void main(String[] args) {
HasSelfPrivateNum numRef = new HasSelfPrivateNum();
ThreadA athread = new ThreadA(numRef);
athread.start();
ThreadB bthread = new ThreadB(numRef);
bthread.start();
}
}
非同步输出结果:
a set over!
b set over!
b num=200
a num=200
加入synchronized关键字同步后,输出结果:
a set over!
a num=100
b set over!
b num=200
用线程访问的对象中如果有多个实例变量,则运行的结果有可能出现交叉的情况
如果对象仅有一个实例变量,则有可能出现覆盖的情况(如上面例子)
需在public void addI(String username)前加关键字synchronized实现同步
在两个线程访问同一个对象中的同步方法时一定是线程安全的(原文)
多个对象多个锁
其他代码与上例相同(+synchronized关键字后的)
package test;
import service.HasSelfPrivateNum;
import extthread.ThreadA;
import extthread.ThreadB;
public class Run {
public static void main(String[] args) {
HasSelfPrivateNum numRef1 = new HasSelfPrivateNum();
HasSelfPrivateNum numRef2 = new HasSelfPrivateNum();
ThreadA athread = new ThreadA(numRef1);
athread.start();
ThreadB bthread = new ThreadB(numRef2);
bthread.start();
}
}
输出结果:
a set over!
b set over!
b num=200
a num=100
两个线程分别访问同一个类的两个不同实例的相同名称的同步方法,效果却是以异步的方式运行的。
原因:此处关键字synchronized取得的锁是对象锁。在多个线程访问同一个对象时,哪个线程先执行带synchronized关键字的方