java之结合代码理解synchronized关键字

为了保证数据的一致性即实现线程的安全性,java虚拟机提供了同步和锁机制。synchronized关键字是最基本的互斥同步手段。除此之外,还可以使用java.util.concurrent包中的重入锁(ReentrantLock)来实现同步。相比synchronized,ReentrantLock增加了一些高级功能,主要有等待可中断、可实现公平锁、锁可以绑定多个条件等。

见SynchronizedDemo.java的源码理解synchronized

/**
 * Synchronized理解:
 *    根据如下4个例子总结如下:
 * Synchronized修饰的方法和Synchronized(this)修饰的代码块功能是一样的,当使用Synchronized修饰的方法或Synchronized(this)修饰的代码块被调用时,当前的实例对象被锁住,因此没有其他线程可以调用该实例对象的这个或任何其他的Synchronized修饰的方法和Synchronized(this)修饰的代码块
 * static Synchronized修饰的方法和Synchronized(*.class)修饰的代码块功能是一样的,当使用static Synchronized修饰的方法或Synchronized(*.class)修饰的代码块被调用时,当前的类对象(例子中的是Sync.class对象)被锁住,因此没有其他线程可以调用同一个类的的这个或任何其他的static Synchronized修饰的方法和Synchronized(*.class)修饰的代码块
 **/
public class SynchronizedDemo{
    /**
     * 例1:
     * 同一个对象:
     * 当一个线程进入一个对象A的synchronized方法的同时,其它线程不能进入该对象的任何synchronized方法
     **/
    private void showSynchronizedResult1(){
        final Sync testSync1 = new Sync();

        Thread thread1 = new Thread(new Runnable(){
            @Override
            public void run(){
                testSync1.run1();
            }
        });

        Thread thread2 = new Thread(new Runnable(){
            @Override
            public void run(){
                testSync1.run2();
            }
        });

        thread1.start();
        thread2.start();
    }

    /**
     * 例2:
     * 同一个对象:
     * 当一个线程进入一个对象A的synchronized方法的同时,其它线程可以进入该对象的普通方法
     **/
    private void showSynchronizedResult2(){
        final Sync testSync1 = new Sync();

        Thread thread1 = new Thread(new Runnable(){
            @Override
            public void run(){
                testSync1.run1();
            }
        });

        Thread thread3 = new Thread(new Runnable(){
            @Override
            public void run(){
                testSync1.run3();
            }
        });

        thread1.start();
        thread3.start();
    }

    /**
     * 例3:
     * 不同对象
     * 当一个线程进入一个对象A的synchronized方法的同时,其它线程可以进入其他对象的synchronized方法,互不影响
     **/
    private void showSynchronizedResult3(){
        final Sync testSync1 = new Sync();
        final Sync testSync2 = new Sync();

        Thread thread1 = new Thread(new Runnable(){
            @Override
            public void run(){
                testSync1.run1();
            }
        });

        Thread thread2 = new Thread(new Runnable(){
            @Override
            public void run(){
                testSync2.run2();
            }
        });

        thread1.start();
        thread2.start();
    }

    /**
     * 例4:
     * 当一个线程进入一个static synchronized方法的同时,其它线程不可以进入任何的static synchronized方法
     **/
    private void showStaticSynchronizedResult4(){
        Thread thread1 = new Thread(new Runnable(){
            @Override
            public void run(){
                Sync.run4();
            }
        });

        Thread thread2 = new Thread(new Runnable(){
            @Override
            public void run(){
                Sync.run5();
            }
        });

        thread1.start();
        thread2.start();
    }

    public static void main(String args[]){
        // 例1:多线程下同一对象的多个Synchronized方法
        new SynchronizedDemo().showSynchronizedResult1();

        // 例2:多线程下同一对象的Synchronized方法和普通方法
        //new SynchronizedDemo().showSynchronizedResult2();

        // 例3:多线程下不同对象的Synchronized方法
        //new SynchronizedDemo().showSynchronizedResult3();

        // 例4:多线程下的多个static Synchronized方法
        //new SynchronizedDemo().showStaticSynchronizedResult4();
    }
}

class Sync{
    public synchronized void run1(){
        for (int i = 0; i < 5; i++){
            System.out.println("execute run1");
            sleepOneSec();
        }
    }

    public synchronized void run2(){
        for (int i = 0; i < 5; i++){
            System.out.println("execute run2");
            sleepOneSec();
        }
    }

    public void run3(){
        for (int i = 0; i < 5; i++){
            System.out.println("execute run3");
            sleepOneSec();
        }
    }

    public static synchronized void run4(){
        for (int i = 0; i < 5; i++){
            System.out.println("execute run4");
            sleepOneSec();
        }
    }

    public static synchronized void run5(){
        for (int i = 0; i < 5; i++){
            System.out.println("execute run5");
            sleepOneSec();
        }
    }

    private static void sleepOneSec(){
        try{
            Thread.sleep(1000);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

原文地址:https://www.cnblogs.com/bravestarrhu/p/java-----synchronized.html

时间: 2024-11-09 10:07:27

java之结合代码理解synchronized关键字的相关文章

java多线程(五)synchronized关键字修饰代码块

转载请注明出处:http://blog.csdn.net/xingjiarong/article/details/47916703 在上一篇博客中我们介绍了synchronized关键字修饰方法的用法,我们接着介绍synchronized关键字.除了修饰方法之外,还可以修饰代码块,一共有以下5种用法. 一.this synchronized(this){ //互斥代码 } 这里的this指的是执行这段代码的对象,synchronized得到的锁就是this这个对象的锁,这种写法等价于我们上一篇博

Java 多线程(六) synchronized关键字详解

Java 多线程(六) synchronized关键字详解 多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题. 同步机制可以使用synchronized关键字实现. 当synchronized关键字修饰一个方法的时候,该方法叫做同步方法. 当synchronized方法执行完或发生异常时,会自动释放锁. 下面通过一个例子来对synchronized关键字的用法进行解析. 1.是否使用synchronized关键字的不同 例子

java的线程同步机制synchronized关键字的理解

线程同步:               由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问. 需要明确的几个问题: 1)synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.如果 再细的分类,synchronized可作用于instance变量.object reference(对象引用).static函数和clas

java并发编程--深入理解volatile关键字

??volatile是一个在java并发编程中耳熟能详的关键字.即使从来没有使用过,你也偶尔会在技术书籍或博客中见到.对volatile关键字的解释常常被一笔带过:被修饰的变量具有可见性,但不能保证原子性.但是到底如何保证可见性,可见性是什么--诸如此类的问题在碰到这种凝练的解释时会产生一种知其然不知其所以然的困惑.那么我将尽力在这一篇文章中将volatile关键字的意义彻底击穿. 可见性 ??可见性,顾名思义,可见程度.假如你在被窝里打开了手电筒,只有你自己知道手电筒打开了,那么可见性就非常差

java多线程编程之使用Synchronized关键字同步类方法

最简单的方法就是使用synchronized关键字来使run方法同步,看下面的代码,只要在void和public之间加上synchronized关键字 复制代码 代码如下: public synchronized void run(){     } 从 上面的代码可以看出,只要在void和public之间加上synchronized关键字,就可以使run方法同步,也就是说,对于同一个Java类的 对象实例,run方法同时只能被一个线程调用,并当前的run执行完后,才能被其他的线程调用.即使当前线

Java多线程(四)—— synchronized关键字续

1.synchronized原理 在java中,每一个对象有且仅有一个同步锁.这也意味着,同步锁是依赖于对象而存在.当我们调用某对象的synchronized方法时,就获取了该对象的同步锁.例如,synchronized(obj)就获取了“obj这个对象”的同步锁.不同线程对同步锁的访问是互斥的.也就是说,某时间点,对象的同步锁只能被一个线程获取到!通过同步锁,我们就能在多线程中,实现对“对象/方法”的互斥访问. 例如,现在有两个线程A和线程B,它们都会访问“对象obj的同步锁”.假设,在某一时

Java多线程之深入理解synchronize关键字

synchronize锁重入: 关键字synchronize拥有锁重入的功能,也就是在使用synchronize时,当一个线程的得到了一个对象的锁后,再次请求此对象是可以再次得到该对象的锁. 当一个线程请求一个由其他线程持有的锁时,发出请求的线程就会被阻塞,然而,由于内置锁是可重入的,因此如果某个线程试图获得一个已经由她自己持有的锁,那么这个请求就会成功,"重入" 意味着获取锁的 操作的粒度是"线程",而不是调用. public class SyncDubbol {

从JAVA看C#中volatile和synchronized关键字的作用

最近一直在想C#中 volatile关键字到底是用来干什么的?查了很多.NET的文章都是说用volatile修饰的变量可以让多线程同时修改,这是什么鬼... 然后查到了下面这篇JAVA中关于volatile和synchronized关键字的概述,总算对volatile和synchronized关键字有了个大概的了解,而C#中应该类似,注意C#中没有synchronized关键字,但是有MethodImplAttribute 类 和 SynchronizationAttribute 类与JAVA中

Java中synchronized关键字理解

好记性不如烂笔头~~ 并发编程中synchronized关键字的地位很重要,很多人都称它为重量级锁.利用synchronized实现同步的基础:Java中每一个对象都可以作为锁.具体表现为以下三种形式. (1)对于普通同步方法,锁是当前实例对象. (2)对于静态同步方法,锁是当前类的Class对象. (3)对于同步方法块,锁是synchronized括号里配置的对象. 一.普通同步方法 使用synchronized关键字修饰一个普通方法,锁住的是当前实例的对象.当synchronized锁住该对