一句话形容Synchronized关键字的作用:能够保证同一时刻,最多只有一个线程执行该段代码,已达到并发安全的效果。
一、对象锁
1、代码块:
package com.example.springwebfluxtest.synchronize;
public class SynchronizedObjectCodeBlock2 implements Runnable {
static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();
@Override
public void run() {
synchronized (this){
System.out.println("我是对象锁的代码块形式"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
}
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("finished");
}
}
运行结果:(保证串行执行)
我是对象锁的代码块形式我叫Thread-1
Thread-1运行结束
我是对象锁的代码块形式我叫Thread-0
Thread-0运行结束
finished
package com.example.springwebfluxtest.synchronize;
public class SynchronizedObjectCodeBlock2 implements Runnable {
static SynchronizedObjectCodeBlock2 instance = new SynchronizedObjectCodeBlock2();
Object lock1 = new Object();
Object lock2 = new Object();
@Override
public void run() {
synchronized (lock1){
System.out.println("我是lock1"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"lock1运行结束");
}
synchronized (lock2){
System.out.println("我是lock2"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"lock2运行结束");
}
}
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("finished");
}
}
运行结果:
我是lock2我叫Thread-0 几乎同时
我是lock1我叫Thread-1
我是lock1我叫Thread-0
Thread-0lock1运行结束
我是lock2我叫Thread-0
我是lock1我叫Thread-1
Thread-0lock2运行结束
Thread-1lock1运行结束
我是lock2我叫Thread-1
Thread-1lock2运行结束
finished
调试技巧:
切换线程
2、普通方法:
package com.example.springwebfluxtest.synchronize;
public class SynchronizedObjectMehod3 implements Runnable {
static SynchronizedObjectMehod3 instance = new SynchronizedObjectMehod3();
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("finished");
}
@Override
public void run() {
method();
}
public synchronized void method(){
System.out.println("我是对象锁的方法修饰符形式"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
}
运行结果:
我是对象锁的方法修饰符形式我叫Thread-1
Thread-1运行结束
我是对象锁的方法修饰符形式我叫Thread-0
Thread-0运行结束
finished
二、类锁
1、synchronized加在static方法上
package com.example.springwebfluxtest.synchronize;
public class SynchronizedClassStatic4 implements Runnable {
static SynchronizedClassStatic4 instance1 = new SynchronizedClassStatic4();
static SynchronizedClassStatic4 instance2 = new SynchronizedClassStatic4();
@Override
public void run() {
method();
}
public static synchronized void method(){
System.out.println("我是类锁的静态方法"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("finished");
}
}
运行结果:
我是类锁的静态方法我叫Thread-1
Thread-1运行结束
我是类锁的静态方法我叫Thread-0
Thread-0运行结束
finished
2、synchronized(*。class)代码块
package com.example.springwebfluxtest.synchronize;
public class SynchronizedClassClass implements Runnable {
static SynchronizedClassClass instance1 = new SynchronizedClassClass();
static SynchronizedClassClass instance2 = new SynchronizedClassClass();
@Override
public void run() {
method();
}
public void method(){
synchronized(SynchronizedClassClass.class){
System.out.println("我是类锁*.class"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
}
public static void main(String[] args) {
Thread t1 = new Thread(instance1);
Thread t2 = new Thread(instance2);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("finished");
}
}
运行结果:
我是类锁*.class我叫Thread-1
Thread-1运行结束
我是类锁*.class我叫Thread-0
Thread-0运行结束
finished
多线程访问同步方法的7种情况
4、同时访问同步与非同步方法:非同步方法不受到影响:
package com.example.springwebfluxtest.synchronize;
public class SynchronizedYesAndNo6 implements Runnable {
static SynchronizedYesAndNo6 instance = new SynchronizedYesAndNo6();
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
method();
}else{
method2();
}
}
public synchronized void method(){
System.out.println("我是同步方法"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public void method2(){
System.out.println("我是非同步方法"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("finished");
}
}
运行结果:
我是非同步方法我叫Thread-1
我是同步方法我叫Thread-0
Thread-0运行结束
Thread-1运行结束
finished
package com.example.springwebfluxtest.synchronize;
public class SynchronizedDifferentMethod7 implements Runnable {
static SynchronizedDifferentMethod7 instance = new SynchronizedDifferentMethod7();
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
method();
}else{
method2();
}
}
public synchronized void method(){
System.out.println("我是同步方法1"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public synchronized void method2(){
System.out.println("我是同步方法2"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("finished");
}
}
运行结果:
我是同步方法1我叫Thread-0
Thread-0运行结束
我是同步方法2我叫Thread-1
Thread-1运行结束
finished
package com.example.springwebfluxtest.synchronize;
public class SynchronizedStaticAndNormal8 implements Runnable {
static SynchronizedStaticAndNormal8 instance = new SynchronizedStaticAndNormal8();
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
method();
}else{
method2();
}
}
public synchronized static void method(){
System.out.println("我是static同步方法1"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public synchronized void method2(){
System.out.println("我非static是同步方法2"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("finished");
}
}
运行结果:
我非static是同步方法2我叫Thread-1
我是static同步方法1我叫Thread-0
Thread-1运行结束
Thread-0运行结束
finished
package com.example.springwebfluxtest.synchronize;
public class SynchronizedException9 implements Runnable {
static SynchronizedException9 instance = new SynchronizedException9();
@Override
public void run() {
if(Thread.currentThread().getName().equals("Thread-0")){
method();
}else{
method2();
}
}
public synchronized void method(){
System.out.println("我是同步方法1"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
throw new Exception();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public synchronized void method2(){
System.out.println("我是同步方法2"+"我叫"+Thread.currentThread().getName());
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"运行结束");
}
public static void main(String[] args) {
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
while(t1.isAlive()||t2.isAlive()){
}
System.out.println("finished");
}
}
运行结果(有问题):
我是同步方法2我叫Thread-1
Thread-1运行结束
我是同步方法1我叫Thread-0
java.lang.Exception
at com.example.springwebfluxtest.synchronize.SynchronizedException9.method(SynchronizedException9.java:18)
at com.example.springwebfluxtest.synchronize.SynchronizedException9.run(SynchronizedException9.java:8)
at java.lang.Thread.run(Thread.java:748)
Thread-0运行结束
finished
视频的结果:
核心思想:
目前我进入到了一个被synchronized修饰的方法,而在这个方法里调用了另外一个没有被synchronized修饰的方法,这个时候线程不是安全的。
synchronized的性质:
1、可重入
情况1:
package com.example.springwebfluxtest.synchronize;
/**
* 可重入粒度测试:递归调用本方法
*/
public class SynchronizedRecursion9 {
int a = 0;
public static void main(String[] args) {
SynchronizedRecursion9 synchronizedRecursion9 = new SynchronizedRecursion9();
synchronizedRecursion9.method1();
}
private synchronized void method1(){
System.out.println("这是method1,a="+a);
if(a == 0){
a++;
method1();
}
}
}
运行结果:
这是method1,a=0
这是method1,a=1
情况2:
package com.example.springwebfluxtest.synchronize;
/**
* 可重入粒度测试2:调用类内部其他的方法
*/
public class SynchronizedRecursion11 {
public static void main(String[] args) {
SynchronizedRecursion11 synchronizedRecursion9 = new SynchronizedRecursion11();
synchronizedRecursion9.method1();
}
public synchronized void method1(){
System.out.println("我是mthod1()");
method2();
}
private synchronized void method2(){
System.out.println("我是method2");
}
}
运行结果:
我是mthod1()
我是method2
情况3:
结果
我是子类方法
我是父类方法
package com.example.springwebfluxtest.synchronize;
import javax.xml.bind.SchemaOutputResolver;
/**
* 可重入粒度测试3:调用父类方法
*/
public class SynchronizedRecursion12 {
public synchronized void doSomething(){
System.out.println("我是父类方法");
}
}
class TestClass extends SynchronizedRecursion12{
public synchronized void doSomething(){
System.out.println("我是子类方法");
super.doSomething();
}
public static void main(String[] args) {
TestClass testClass = new TestClass();
testClass.doSomething();
}
}