在多线程的情况下,由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。
由于我们可以通过 private 关键字来保证数据对象只能被方法访问,所以我们只需针对方法提出一套机制,这套机制就是 synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。
1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。
在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为 synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。
public class TraditionalThreadSynchronized  {
     
    public static void main(String[] args) {
        new TraditionalThreadSynchronized().init();
    }
    void init(){
        final Outputer out  = new Outputer();
        //线程1
        new Thread(new Runnable(){
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    out.output1("Tmethod--->AAAAAA");
                }
            }
              
        }).start();
        //线程2
        new Thread(new Runnable(){
            @Override
            public void run() {
                while(true){
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    out.output3("Tmethod--->BBBBBB");
                }
            }
             
        }).start();
    } //end main
     
    static class Outputer{  //内部类
        /**
         * 方法内部加上线程锁,线程的锁只能锁同一个对象,如果有static方法那么线程锁必须为Class,不能为this
         */
        public void output1(String name){
            int len =name.length();
            synchronized (Outputer.class){ //synchronized参数可以为this,但是和static方法不能实现互斥,实现互斥只能为同一个对象
                for(int i=0;i<len;i++){
                    System.out.print(name.charAt(i));
                }
                System.out.println();
            }
        }
        /**
         * output2 和 output3不能实现同步,output2用的是对象锁的是this而output3是static方法要锁的话只能用class,如:output1
         * @param name
         */
        public synchronized void output2(String name){ //直接把锁加在方法上,默认把synchronized加载方法上那么他的互斥对象为this
            int len =name.length();
                for(int i=0;i<len;i++){
                    System.out.print(name.charAt(i));
                }
                System.out.println();
        }
        //static方法的线程锁
        public static synchronized void output3(String name){
            int len =name.length();
            for(int i=0;i<len;i++){
                System.out.print(name.charAt(i));
            }
            System.out.println();
        }
    }
}

synchronized同步锁的更多相关文章

  1. Java中String做为synchronized同步锁使用详解

    Java中使用String作同步锁 在Java中String是一种特殊的类型存在,在jdk中String在创建后是共享常量池的,即使在jdk1.8之后实现有所不同,但是功能还是差不多的. 借助这个特点 ...

  2. Java进程与多线程+线程中的join、yield、wait等方法+synchronized同步锁使用

    首先了解什么是多线程与进程 进程:是一个执行过程,动态的概念 --->会分配内存线程:是进程的一个单元,线程是系统最小的执行单元 详解: http://blog.csdn.net/luoweif ...

  3. 深入研究 synchronized 同步锁 作用于 静态方法 和 非静态方法 的 区别

    1.前言 众所周知, synchronized 是同步锁 ,虽然在底层又细分了无锁.偏向锁.轻量级锁.自旋锁 以及重量级锁 机制, 这些底层锁知道一下原理即可 ,[想要 了解 这篇 博文 有 解释 : ...

  4. 继承Runnable 实现Synchronized 同步锁

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  5. 三、synchronized同步锁

    一.简介 在Java多线程中,我们要实现同步串行最早接触的就是synchronized关键字. 基本语法如下: synchronized(锁) { // 代码块 } sychronized关键字的锁主 ...

  6. 2.synchronized同步锁

    原文链接:http://blog.csdn.net/zteny/article/details/54863391 简介 synchronized是Java语言的一个关键字,用来修饰一个方法或者代码块, ...

  7. synchronized同步锁+单利模式

    public static synchronized VolleyRequestController getInstance() {         if (sInstance == null) { ...

  8. Java中String做为synchronized同步锁

    synchronized (("" + userId).intern()) { // TODO:something } JVM内存区域里面有一块常量池,关于常量池的分配: JDK6 ...

  9. synchronized同步代码块锁释放

    今天发现自己写的线上程序出现数据库不能同步的问题,查看日志已经停止记录,随后使用jstack查看线程的运行状况,发现有个同步线程锁住了. 以下是jstack -l 637  问题线程的内容. &quo ...

随机推荐

  1. 【OCP题库-12c】最新CUUG OCP 071考试题库(72题)

    72.View the exhibit for the structure of the STUDENTand FACULTYtables. STUDENT Name Null? Type ----- ...

  2. “全栈2019”Java异常第二章:如何处理异常?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  3. Mybatis 动态Sql语句《常用》

    MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格,还要注意省掉 ...

  4. Jmeter_RabbitMQ性能测试

    [前言] RabbitMQ消息的传递并非使用HTTP协议,而是AMQP协议,因此除非开发暴露一个HTTP请求接口出来,否则无法直接使用HTTP请求发送json串数据,实现数据publish到MQ中. ...

  5. 【文文殿下】后缀自动机(Suffix Automaton,SAM)学习笔记

    前言 后缀自动机是一个强大的数据结构,能够解决很多字符串相关的(String-related)问题. 例如:他可以查询一个字符串在另一个字符串中出现的所有子串,以及查询一个字符串中本质不同的字符串的个 ...

  6. luoguP5074 Eat the Trees

    https://www.luogu.org/problemnew/show/P5074 插头 $ dp $ 入门题 如果你还不会插头 $ dp $ 请右转 洛谷插头dp题解 虽然是入门题但还是逃不过分 ...

  7. ORM的查询操作

    查询的分类 class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() ...

  8. IT男装逼利器:如何像黑客一样聊天 Mojo-Webqq

    电影里的黑客们聊天不想我们生活中的一样,用QQ.微信的客户端,都是通过命令行来进行聊天交流的,大概是为了提升逼格吧.(文末有福利~) 本文作者:KevinSVIP 今天发现一个有趣的项目:使用mojo ...

  9. Spring Boot启动过程(六):内嵌Tomcat中StandardHost、StandardContext和StandardWrapper的启动

    看代码有助于线上出现预料之外的事的时候,不至于心慌... StandardEngine[Tomcat].StandardHost[localhost]的启动与StandardEngine不在同一个线程 ...

  10. k-近邻算法 python实现

    必要的注释已经写在code里面了: import operator from numpy import* def init(): grp=array([[1.0,1.1],[1.0,1.0],[0,0 ...