美文网首页
synchronized的用法

synchronized的用法

作者: 捉虫大师 | 来源:发表于2018-08-10 21:54 被阅读8次

在java中,关键字synchronized可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作),同时我们还应该注意到synchronized另外一个重要的作用,synchronized可保证一个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可见性,完全可以替代Volatile功能)

用法

  • 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁;
  • 修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁;
  • 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁。
修饰实例方法
package thread;

public class ThreadSynchronized1 implements Runnable {

    private static int i = 0;

    private synchronized void increase() {
        i++;
    }

    @Override
    public void run() {
        for (int j = 0; j < 2000; j++) {
            increase();
        }
    }

    public static void main(String[] args) {
        ThreadSynchronized1 thread = new ThreadSynchronized1();
        Thread thread1 = new Thread(thread);
        Thread thread2 = new Thread(thread);
        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (Exception e) {

        }
        System.out.println(i);

    }
}

这里i是临界资源,i++不是原子操作,不论运行多少次,最终永远是4000。
但如果去掉synchronized关键字,那么结果每次运行可能都不一样。这里也有一个小坑,如果new了两个ThreadSynchronized1分别作为Runnable传到Thread中,那么结果也会错乱,就像这样,所以用在实例方法上一定要小心是哪个实例。

...
        Thread thread1 = new Thread(new ThreadSynchronized1());
        Thread thread2 = new Thread(new ThreadSynchronized1());
...
修饰静态方法

针对刚刚实例方法的修饰会有小坑,这里还有另一种解决办法,那就是把方法变成静态方法。

package thread;

public class ThreadSynchronized2 implements Runnable {

    private static int i = 0;

    private static synchronized void increase() {
        i++;
    }

    @Override
    public void run() {
        for (int j = 0; j < 2000; j++) {
            increase();
        }
    }

    public static void main(String[] args) {
        ThreadSynchronized2 thread = new ThreadSynchronized2();
        Thread thread1 = new Thread(new ThreadSynchronized2());
        Thread thread2 = new Thread(new ThreadSynchronized2());
        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (Exception e) {

        }
        System.out.println(i);

    }
}

这样就不会有问题了。

修饰代码块
package thread;

public class ThreadSynchronized3 implements Runnable {

    private static int i = 0;

    private void increase() {
        i++;
    }

    @Override
    public void run() {
        for (int j = 0; j < 2000; j++) {
            synchronized (this) {
                increase();
            }
        }
    }

    public static void main(String[] args) {
        ThreadSynchronized3 thread = new ThreadSynchronized3();
        Thread thread1 = new Thread(thread);
        Thread thread2 = new Thread(thread);
        thread1.start();
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (Exception e) {

        }
        System.out.println(i);
    }
}

这里也要保证synchronized (this) 中的this是同一个对象,比如这样锁又会失效:

...
        Thread thread1 = new Thread(new ThreadSynchronized3());
        Thread thread2 = new Thread(new ThreadSynchronized3());
...

总结:synchronized很好用但是一定要保证用的是“同一把锁”。

synchronized原理

这里简单引用一下别人的文章

实现原理: JVM 是通过进入、退出对象监视器( Monitor )来实现对方法、同步块的同步的。具体实现是在编译之后在同步方法调用前加入一个 monitor.enter 指令,在退出方法和异常处插入 monitor.exit 的指令。
其本质就是对一个对象监视器( Monitor )进行获取,而这个获取过程具有排他性从而达到了同一时刻只能一个线程访问的目的。
而对于没有获取到锁的线程将会阻塞到方法入口处,直到获取锁的线程 monitor.exit 之后才能尝试继续获取锁。

这几天在github上看到这个项目感觉很棒
https://github.com/crossoverJie/Java-Interview
里面分类目写了很多java内容,对查找资料很有帮助。

相关文章

  • Java @ synchronized

    参考: Java中Synchronized的用法 Java 多线程:synchronized 关键字用法(修饰类,...

  • ios 线程锁

    ios多线程之线程锁 1.@synchronized的用法 @synchronized(self)的用法: @sy...

  • 并发编程的锁机制:synchronized和lock

    synchronized Java中Synchronized的用法 synchronized对于同步方法,锁是当前...

  • iOS中关于synchronized的使用

    @synchronized(self)的用法

  • Java并发目录

    一、简述 线程状态与方法 synchronized 用法 ReentrantLock用法 Semaphore用法 ...

  • java对象锁和类

    synchronized修饰非静态方法,同步代码快的synchronized (this)用法和synchroni...

  • 春招笔记(一)腾讯

    1.synchronize用法 synchronized 方法:通过在方法声明中加入 synchronized关键...

  • synchronized 用法

    一、代码示例 1.synchronized修饰普通方法 synchronized修饰普通代码,加锁对象为调用这个方...

  • synchronized用法

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

  • synchronized用法

    互斥锁:当一线程进入synchronized修饰的代码块或者方法,其它线程等待,知道锁被释放;内置锁:对象锁,每个...

网友评论

      本文标题:synchronized的用法

      本文链接:https://www.haomeiwen.com/subject/gqolbftx.html