文章目录
论证
修饰方法
静态方法 锁定的是类
非静态方法 锁定的是实例对象本身修饰代码块 锁定的是传入的对象
作用域为全局
1.首先创建线程调用类
修饰方法时
public class TestPrint {
public static void main(String[] args) {
Print print= new Print();
new Thread(()->{
print.fun1();
},"A").start();
new Thread(()->{
print.fun2();
},"A").start();
}
}
class Print{
public void fun1(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1....");
}
public void fun2(){
System.out.println("2....");
}
}
控制台为
2.修饰非静态方法 锁住的是实例对象本身
一个对象(资源类实例化)里面如果有多个synchronized方法,某一时刻只要有一个线程去访问其中一个synchronized方法,其他线程都只能在外等待。换句话说,同一时刻,只能有唯一的线程去访问这些synchronized方法,锁的是当前对象的this,被锁定后,其他的线程都不能进入到当前对象的其他synchronized方法。
把两个方法(非静态)加上synchronized修饰 A线程获取到print对象后 B线程只能在外等待
public class TestPrint {
public static void main(String[] args) {
Print print= new Print();
new Thread(()->{
print.fun1();
},"A").start();
new Thread(()->{
print.fun2();
},"B").start();
}
}
class Print{
public synchronized void fun1(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1....");
}
public synchronized void fun2(){
System.out.println("2....");
}
}
把两个方法(非静态)加上synchronized修饰 print对象执行A线程 print1对象执行B线程 无需等待
public class TestPrint {
public static void main(String[] args) {
Print print = new Print();
Print print1 = new Print();
new Thread(()->{
print.fun1();
},"A").start();
new Thread(()->{
print1.fun2();
},"B").start();
}
}
class Print{
public synchronized void fun1(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1....");
}
public synchronized void fun2(){
System.out.println("2....");
}
}
只对fun1(非静态)加上synchronized修饰 A线程获取到print对象后 B也可以执行fun2 无需等待
public class TestPrint {
public static void main(String[] args) {
Print print = new Print();
new Thread(()->{
print.fun1();
},"A").start();
new Thread(()->{
print.fun2();
},"B").start();
}
}
class Print{
public synchronized void fun1(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1....");
}
public void fun2(){
System.out.println("2....");
}
}
3.修饰静态方法 锁定的是类(可以说 类是Class的对象)
对两个方法都修饰 synchronized static 看出print1对象需要等待print对象执行完才能执行
public class TestPrint {
public static void main(String[] args) {
Print print = new Print();
Print print1 = new Print();
new Thread(()->{
print.fun1();
},"A").start();
new Thread(()->{
print1.fun2();
},"A").start();
}
}
class Print{
public static synchronized void fun1(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1....");
}
public static synchronized void fun2(){
System.out.println("2....");
}
}
4. 修饰代码块时
创建for循环线程调用 可看出是并行的
public class TestPrint {
public static void main(String[] args) {
Print print = new Print();
for (int i =0;i< 5;i++){
new Thread(()->{
print.fun();
},"A").start();
}
}
}
class Print{
public void fun(){
System.out.println("开始....");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束....");
}
}
当我加入this 开始等待了 五个线程只有一个资源(对象) this锁住的调用的对象
public class TestPrint {
public static void main(String[] args) {
Print print = new Print();
for (int i =0;i< 5;i++){
new Thread(()->{
print.fun();
},"A").start();
}
}
}
class Print{
public void fun(){
synchronized (this){
System.out.println("开始....");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束....");
}
}
}
当我把new Print()放到循环里面 就变成了每个线程各有一个资源(对象) 结果就是并行
public class TestPrint {
public static void main(String[] args) {
for (int i =0;i< 5;i++){
Print print = new Print();
new Thread(()->{
print.fun();
},"A").start();
}
}
}
class Print{
public void fun(){
synchronized (this){
System.out.println("开始....");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束....");
}
}
}
当我synchronized(类.Class)之后 锁着的是当前类 无论多少个对象来访问都需等待
public class TestPrint {
public static void main(String[] args) {
for (int i =0;i< 5;i++){
Print print = new Print();
new Thread(()->{
print.fun();
},"A").start();
}
}
}
class Print{
public void fun(){
synchronized (Print.class){
System.out.println("开始....");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束....");
}
}
}
当我用“1”放入()中 代码也会等待 “1”只有一份
public class TestPrint {
public static void main(String[] args) {
Print print = new Print();
for (int i =0;i< 5;i++){
new Thread(()->{
print.fun();
},"A").start();
}
}
}
class Print{
public void fun(){
synchronized ("1"){
System.out.println("开始....");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束....");
}
}
}
当我用num参数放入()中 让调用者传入num 如果num是同一个地址 线程也会等待
public class TestPrint {
public static void main(String[] args) {
Print print = new Print();
for (int i =0;i< 5;i++){
Integer num = 1;
new Thread(()->{
print.fun(num);
},"A").start();
}
}
}
class Print{
public void fun(Integer num){
synchronized (num){
System.out.println("开始....");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束....");
}
}
}
当我用num参数放入()中 让调用者每次传入new num num地址不同 线程不会等待
public class TestPrint {
public static void main(String[] args) {
Print print = new Print();
for (int i =0;i< 5;i++){
Integer num = new Integer(1);
new Thread(()->{
print.fun(num);
},"A").start();
}
}
}
class Print{
public void fun(Integer num){
synchronized (num){
System.out.println("开始....");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("结束....");
}
}
}
5. synchronized()修饰代码块时 锁住的作用域
建立person类
在这里插入代码片
@Service
public class Person {
public void fun1(){
synchronized ("111"){
System.out.println("存钱开始");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("存钱结束");
}
}
}
建立student类
@Service
public class Student {
public void fun2(){
synchronized("111"){
System.out.println("花钱开始");
System.out.println("花钱结束");
}
}
}
建立测试controller
@RestController
public class ceshi {
@Autowired
Person person;
@Autowired
Student student;
@RequestMapping("/xian")
public void ceeshi(){
new Thread(()->{
person.fun1();
},"A").start();
new Thread(()->{
student.fun2();
},"B").start();
}
}
当我用postman访问接口 student对象会等待person对象执行完 才执行 由此可得synchronized修饰代码块()传入参数地址一样 作用域为全局