synchronized同步方法:
方法内的变量为线程安全;
实例变量非线程安全:
如果多个线程共同访问一个对象中的实例变量,则有可能出现“非线程安全”问题;
加关键字synchronized : 在两个线程访问同一个对象中的同步方法一定是线程安全的。
public class HasSelfPrivateNum {
synchronized public void addI(String username) {
try {
int num = 0;
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();
}
}
}
public class RunHS {
public static void main(String[] args) {
HasSelfPrivateNum numRef = new HasSelfPrivateNum();
ThreadA threada = new ThreadA(numRef);
threada.start();
ThreadB threadb = new ThreadB(numRef);
threadb.start();
}
}
public class ThreadA extends Thread{
private HasSelfPrivateNum numRef;
public ThreadA(HasSelfPrivateNum numRef) {
super();
this.numRef = numRef;
}
public void run() {
super.run();
numRef.addI("a");
}
}
public class ThreadB extends Thread{
private HasSelfPrivateNum numRef;
public ThreadB(HasSelfPrivateNum numRef) {
super();
this.numRef = numRef;
}
public void run() {
super.run();
numRef.addI("b");
}
}
多个对象多个锁:
public class HasSelfTwoLock {
private int num = 0;
synchronized 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();
}
}
}
public class RunTAB {
public static void main(String[] args) {
HasSelfTwoLock numRef1 = new HasSelfTwoLock();
HasSelfTwoLock numRef2 = new HasSelfTwoLock();
ThreadTA threada = new ThreadTA(numRef1);
threada.start();
ThreadTB threadb = new ThreadTB(numRef2);
threadb.start();
}
}
public class ThreadTA extends Thread{
private HasSelfTwoLock numRef;
public ThreadTA(HasSelfTwoLock numRef) {
super();
this.numRef = numRef;
}
public void run() {
super.run();
numRef.addI("a");
}
}
public class ThreadTB extends Thread{
private HasSelfTwoLock numRef;
public ThreadTB(HasSelfTwoLock numRef) {
super();
this.numRef = numRef;
}
public void run() {
super.run();
numRef.addI("b");
}
}
关键字synchronized取得的锁都是对象锁,而不是把一段代码或方法当作锁;
public class MyObject {
synchronized public void methodA() {
try {
System.out.println("begin methodA threadName = "
+ Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("end");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void methodB() {
try {
System.out.println("begin methodB threadName = "
+ Thread.currentThread().getName());
Thread.sleep(5000);
System.out.println("end");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class RunOb {
public static void main(String[] args) {
MyObject object = new MyObject();
ThreadA threada = new ThreadA(object);
threada.setName("A");
ThreadB threadb = new ThreadB(object);
threadb.setName("B");
threada.start();
threadb.start();
}
}
public class ThreadA extends Thread{
private MyObject object;
public ThreadA(MyObject object) {
super();
this.object = object;
}
public void run() {
super.run();
object.methodA();
}
}
public class ThreadB extends Thread{
private MyObject object;
public ThreadB(MyObject object) {
super();
this.object = object;
}
public void run() {
super.run();
object.methodB();
}
}
1)A线程先持有object对象的Lock锁,B线程可以以异步的方式调用object对象中的非synchronized类型的方法;
2)A线程先持有object对象的Lock锁,B线程如果在这时候调用object对象中的synchronized类型的方法则需等待,也就是同步;
脏读:
脏读(dirtyRead)一定会出现操作实例变量的情况下,这就是不同线程“争抢”实例变量的结果;
public class PublicVar {
public String username = "A";
public String password = "AA";
synchronized public void setValue(String username, String password) {
try {
this.username = username;
Thread.sleep(5000);
this.password = password;
System.out.println("setValue method thread name = "
+ Thread.currentThread().getName() + " username = "
+ username + " password = " + password);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
synchronized public void getValue(){
System.out.println("getValue method thread name = "
+ Thread.currentThread().getName() + " username = "
+ username + " password" + password);
}
}
public class Test {
public static void main(String[] args) {
try {
PublicVar publicVarRef = new PublicVar();
ThreadA thread = new ThreadA(publicVarRef);
thread.start();
Thread.sleep(200);
publicVarRef.getValue();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class ThreadA extends Thread{
private PublicVar publicVar;
public ThreadA(PublicVar publicVar) {
super();
this.publicVar = publicVar;
}
public void run() {
super.run();
publicVar.setValue("B", "BB");
}
}
出现脏读时因为 getValue方法并不是同步的,所以可以在任意时候进行调用;加上synchronized关键字;
synchronized锁重入:
当一个线程得到一个对象锁后,再次请求此对象锁时是可以再次得到该对象的锁的;
这也证明在一个synchronized方法/块的内部调用本类的其他synchronized方法/块时,是永远可以得到锁的;
可重入锁也支持在父子类继承的环境中;
出现异常,锁自动释放;
同步不具有继承性;
public class Service {
synchronized public void service1() {
System.out.println("service 111");
service2();
}
synchronized public void service2() {
System.out.println("service 222");
service3();
}
synchronized public void service3() {
System.out.println("service 333");
}
}
public class Sub extends Main{
synchronized public void operateISubMethod() {
try {
while(i > 0) {
i--;
System.out.println("sub print i = " + i);
Thread.sleep(100);
this.operateIMainMethod();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Main {
public int i = 10;
synchronized public void operateIMainMethod() {
try {
i--;
System.out.println("main print i = " + i);
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class RunMT {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}
synchronized同步语句块:
public class CommonUtils {
public static long beginTime1;
public static long endTime1;
public static long beginTime2;
public static long endTime2;
}
public class Task {
private String getData1;
private String getData2;
public void doLongTimeTask() {
try {
System.out.println("begin task");
Thread.sleep(3000);
String privateGetData1 = "return111 threadName = " + Thread.currentThread().getName();
String privateGetData2 = "return222 threadName = " + Thread.currentThread().getName();
synchronized(this) {
getData1 = privateGetData1;
getData2 = privateGetData2;
}
System.out.println(getData1);
System.out.println(getData2);
System.out.println("end task");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Thread1 extends Thread{
private Task task;
public Thread1 (Task task) {
super();
this.task = task;
}
public void run() {
super.run();
CommonUtils.beginTime1 = System.currentTimeMillis();
task.doLongTimeTask();
CommonUtils.endTime1 = System.currentTimeMillis();
}
}
public class Thread2 extends Thread{
private Task task;
public Thread2 (Task task) {
super();
this.task = task;
}
public void run() {
super.run();
CommonUtils.beginTime2 = System.currentTimeMillis();
task.doLongTimeTask();
CommonUtils.endTime2 = System.currentTimeMillis();
}
}
public class Run12 {
public static void main(String[] args) {
Task task = new Task();
Thread1 t1 = new Thread1(task);
t1.start();
Thread2 t2 = new Thread2(task);
t2.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
long beginTime = CommonUtils.beginTime1;
if (CommonUtils.beginTime2 < CommonUtils.beginTime1) {
beginTime = CommonUtils.beginTime2;
}
long endTime = CommonUtils.beginTime1;
if (CommonUtils.beginTime2 > CommonUtils.beginTime1) {
endTime = CommonUtils.endTime2;
}
System.out.println("Time == " + ((endTime - beginTime)/ 1000D));
}
}
synchronized同步代码块的使用:
//用同步代码块解决同步方法的弊端
public class RunOAB {
public static void main(String[] args) {
ObjectService service = new ObjectService();
ThreadA a = new ThreadA(service);
a.setName("a");
a.start();
ThreadB b = new ThreadB(service);
b.setName("b");
b.start();
}
}
public class ObjectService {
public void serviceMethod() {
try {
synchronized(this) {
System.out.println("begin time = " + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("end end = " + System.currentTimeMillis());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class ThreadA extends Thread{
private ObjectService service;
public ThreadA(ObjectService service) {
super();
this.service = service;
}
public void run() {
super.run();
service.serviceMethod();
}
}
public class ThreadB extends Thread{
private ObjectService service;
public ThreadB(ObjectService service) {
super();
this.service = service;
}
public void run() {
super.run();
service.serviceMethod();
}
}
当一个线程访问object的一个synchronized同步代码块时,
另一个线程仍然可以访问该object对象中的非synchronized(this)的同步代码块
一半同步,一半异步:
public class Task {
public void doLongTimeTask() {
for (int i = 0; i < 100; i++) {
System.out.println("Nosynchronized threadName == "
+ Thread.currentThread().getName() + " i = " + (i + 1));
}
System.out.println("");
synchronized (this) {
for (int i = 0; i < 100; i++) {
System.out.println("Synchronized threadName == "
+ Thread.currentThread().getName() + " i = " + (i + 1));
}
}
}
}
//一半同步,一半异步
public class RunAB {
public static void main(String[] args) {
Task task = new Task();
ThreadA ta = new ThreadA(task);
ta.start();
ThreadB tb = new ThreadB(task);
tb.start();
}
}
public class ThreadA extends Thread{
private Task task;
public ThreadA(Task task) {
super();
this.task = task;
}
public void run(){
super.run();
task.doLongTimeTask();
}
}
public class ThreadB extends Thread{
private Task task;
public ThreadB(Task task) {
super();
this.task = task;
}
public void run(){
super.run();
task.doLongTimeTask();
}
}
不在synchronized块中就是异步执行,在synchronized块中就是同步执行;
将任意对象作为对象监视器:
(1)synchronized同步方法
1)对其他synchronized同步方法或synchronized(this)同步代码块调用呈阻塞状态
2)同一时间只有一个线程可以执行synchronized同步方法的代码
(2)synchronized(this)同步代码块
1)对其他同步方法或同步代码块调用呈阻塞状态
2)同一时间只有一个线程可以执行同步代码块的代码