Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。Synchronized的作用主要有三个:
能够保证同一时刻只有一个线程执行该段代码,保证程序的并发安全性
(1)确保线程互斥的访问同步代码
(2)保证共享变量的修改能够及时可见
(3)有效解决重排序问题。
问题,如果两个线程同时count++,最后结果比预计的少
public class SynchronizedTest implements Runnable {
public static int count=0;
static SynchronizedTest instance01=new SynchronizedTest();
public static void main(String[] args) throws InterruptedException {
Thread thread01=new Thread(instance01);
Thread thread02=new Thread(instance01);
thread01.start();
thread02.start();
thread01.join();
thread02.join();
System.out.println("wwqwq"+count);
}
@Override
public void run() {
for(int i=0;i<2000;i++){
count++;
}
}
}
结果是
并不是20000
原因
(1)读取count
(2)将count 加一
(3) 写入内存
Synchronized 锁分为
一、 对象锁
(1)Synchronized 代码块
public class SynchronizedTest implements Runnable {
public static void main(String[] args) {
SynchronizedTest instance=new SynchronizedTest();
Thread thread01=new Thread(instance);
Thread thread02=new Thread(instance);
thread01.start();
thread02.start();
}
@Override
public void run() {
try {
Thread.sleep(3000);
synchronized (this) {
System.out.println("我是线程"+Thread.currentThread().getName()+"开始执行");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是线程"+Thread.currentThread().getName()+"执行结束");
}
}
(2)Synchronized 修饰的普通方法
public class SynchronizedTest implements Runnable {
public static void main(String[] args) {
SynchronizedTest instance=new SynchronizedTest();
Thread thread01=new Thread(instance);
Thread thread02=new Thread(instance);
thread01.start();
thread02.start();
}
@Override
public void run() {
try {
Thread.sleep(3000);
method();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是线程"+Thread.currentThread().getName()+"执行结束");
}
public synchronized void method(){
System.out.println("我是线程"+Thread.currentThread().getName()+"开始执行");
}
}
二 、类锁
(1)Synchronized 指定对象
public class SynchronizedTest implements Runnable {
public static void main(String[] args) {
SynchronizedTest instance01=new SynchronizedTest();
SynchronizedTest instance02=new SynchronizedTest();
Thread thread01=new Thread(instance01);
Thread thread02=new Thread(instance02);
thread01.start();
thread02.start();
}
@Override
public void run() {
try {
Thread.sleep(3000);
synchronized (SynchronizedTest.class) {
System.out.println("我是线程"+Thread.currentThread().getName()+"开始执行");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是线程"+Thread.currentThread().getName()+"执行结束");
}
}
(2)Synchronized 修饰的静态方法
public class SynchronizedTest implements Runnable {
public static void main(String[] args) {
SynchronizedTest instance01=new SynchronizedTest();
SynchronizedTest instance02=new SynchronizedTest();
Thread thread01=new Thread(instance01);
Thread thread02=new Thread(instance02);
thread01.start();
thread02.start();
}
@Override
public void run() {
try {
Thread.sleep(3000);
synchronized (SynchronizedTest.class) {
System.out.println("我是线程"+Thread.currentThread().getName()+"开始执行");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是线程"+Thread.currentThread().getName()+"执行结束");
}
}
缺点
效率低:锁的释放情况少,试图获得锁时不能设定超时,不能中断一个正在试图获得锁的线程
不够灵活:加锁和释放错时机单一,有单一条件的(某个对象),可能是不够的
无法是否成功获取到锁
总结
1,一把锁只能同时被一个线程获取,没有拿到锁的线程必须等待
2,每个实例都有对应有自己的一把锁,不同的实例之间互不影响;例外
锁对象是*.class以及synchronized修饰的是static方法的时候,所有对象共用同一把锁
3,无论是方法正常执行完毕或者方法抛出的异常,都会释放锁