synchronized学习

简介: synchronized 简介synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;  3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;  4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

synchronized 简介

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;   2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;   3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;   4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

synchronized使用

synchronized 修饰代码块

synchronized后跟括号,括号里是变量,这样,一次只有一个线程进入该代码块。

例如:

public static void main(String[] args) {
        TestSyn TestSyn = new TestSyn();
        Thread test1 = new Thread( TestSyn, "Thread-1");
        Thread test2 = new Thread(TestSyn, "Thread-2");
        test1.start();
        test2.start();
    }
    @Override
    public void run() {
        synchronized (this) {
            int i=0;
            while (i<5) {
                System.out.println(Thread.currentThread().getName()+":"+i);
                i++;
            }
        }
    }

运行结果如下:

Thread-1:0
Thread-1:1
Thread-1:2
Thread-1:3
Thread-1:4
Thread-2:0
Thread-2:1
Thread-2:2
Thread-2:3
Thread-2:4

当两个并发线程(thread1和thread2)访问同一个对象(syncThread)中的synchronized代码时 在同一时刻只能有一个线程得到执行, 另一个线程受阻塞,必须等待当前线程执行完这个代码块以后才能执行该代码块。

当两个线程都是新建一个对象去执行的,对象的锁也是两个,方法就会同时执行

public static void main(String[] args) {
        TestSyn TestSyn = new TestSyn();
        TestSyn TestSyn2 = new TestSyn();
        Thread test1 = new Thread( TestSyn, "Thread-1");
        Thread test2 = new Thread(TestSyn2, "Thread-2");
        test1.start();
        test2.start();
    }
    @Override
    public void run() {
        synchronized (this) {
            int i=0;
            while (i<5) {
                System.out.println(Thread.currentThread().getName()+":"+i);
                i++;
            }
        }
    }

运行结果如下:

Thread-1:0
Thread-2:0
Thread-2:1
Thread-2:2
Thread-2:3
Thread-2:4
Thread-1:1
Thread-1:2
Thread-1:3
Thread-1:4

synchronized 修饰方法

方法声明时使用,放在范围操作符(public等)后,其返回类型声明(void等)之前。即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候,当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.

例如:

public static void main(String[] args) {
        TestSyn TestSyn = new TestSyn();
        Thread test1 = new Thread( TestSyn, "Thread-1");
        Thread test2 = new Thread(TestSyn, "Thread-2");
        test1.start();
        test2.start();
    }
    @Override
    public synchronized void run() {
         for (int i = 0; i < 5; i++) {
                System.out.println( Thread.currentThread().getName() + ":"+i);
        }
    }

synchronized 修饰静态方法

synchronized修饰的静态方法锁定的是这个类的所有对象。

例如:

public static void main(String[] args) {
        TestSyn TestSyn = new TestSyn();
        Thread test1 = new Thread( TestSyn, "Thread-1");
        Thread test2 = new Thread(TestSyn, "Thread-2");
        test1.start();
        test2.start();
    }
    @Override
    public void run() {
        method();
    }
    public synchronized static void method() {
        for (int i = 0; i < 5; i++) {
                System.out.println( Thread.currentThread().getName() + ":"+i);
        }
    }

synchronized 修饰类

synchronized后面括号里是一对象,给class加锁和上面的给静态方法加锁的方式是一样的,所有对象都共用同一把锁。

例如:

public static void method() {
            synchronized(TestSyn.class) {
                for (int i = 0; i < 5; i ++) {
                    System.out.println(Thread.currentThread().getName() + ":" + i);
                }
            }
        }
        public synchronized void run() {
            method();
        }
    }

总结

  • 无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;
  • 如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是对类,该类所有的对象同一把锁。
  • 每个对象只有一个锁(lock)与之相关联,谁拿到这个锁谁就可以运行它所控制的那段代码。


相关文章
|
7月前
|
Java 编译器
synchronized原理
synchronized原理
|
7月前
|
Java
【面试问题】Synchronized 和 ReentrantLock 区别?
【1月更文挑战第27天】【面试问题】Synchronized 和 ReentrantLock 区别?
|
4月前
|
存储 Java 程序员
synchronized的原理以及与ReentrantLock的区别
`synchronized`和`ReentrantLock`均为Java线程同步机制,确保共享资源的单一时刻独占访问。`synchronized`关键字直接嵌入JVM,可通过修饰方法或代码块实现对象锁或监视器锁,具备可重入性,依赖Mark Word进行锁状态管理。`ReentrantLock`则需显式调用`lock()`和`unlock()`,提供更灵活控制,如公平锁、尝试锁及条件变量。两者在语法、灵活性和异常处理上有所差异,但均支持可重入性。性能方面,随JDK优化,`synchronized`在某些场景下甚至优于`ReentrantLock`。选择使用哪个取决于具体需求和上下文。
|
3月前
|
缓存 Java 编译器
JAVA并发编程synchronized全能王的原理
本文详细介绍了Java并发编程中的三大特性:原子性、可见性和有序性,并探讨了多线程环境下可能出现的安全问题。文章通过示例解释了指令重排、可见性及原子性问题,并介绍了`synchronized`如何全面解决这些问题。最后,通过一个多窗口售票示例展示了`synchronized`的具体应用。
|
5月前
|
安全 Java 开发者
Java多线程:synchronized关键字和ReentrantLock的区别,为什么我们可能需要使用ReentrantLock而不是synchronized?
Java多线程:synchronized关键字和ReentrantLock的区别,为什么我们可能需要使用ReentrantLock而不是synchronized?
64 0
|
6月前
|
存储 Java
Java并发编程 Synchronized原理
Java并发编程 Synchronized原理
27 0
|
7月前
|
安全 Java 调度
Java多线程- synchronized关键字总结
Java多线程- synchronized关键字总结
52 0
|
前端开发 Java Spring
方法上加上 synchronized 就可以了么
方法上加上 synchronized 就可以了么
|
存储 设计模式 缓存
synchronized原理剖析
synchronized原理剖析
|
Java
Java并发编程系列3 - synchronized
看这篇文章前,建议大家先看我前面的文章《Java并发编程系列1-基础知识》,否则里面的相关知识看不懂,特别是并发编程相关的可见性、有序性,以及内存模型JMM等。 在Java中,关键字synchronized可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作),同时我们还应该注意到synchronized另外一个重要的作用,synchronized可保证一个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可见性,完全可以替代Volatile功能)。
98 1
Java并发编程系列3 - synchronized