同步锁分类

对象锁(this)

类锁(类的字节码文件对象即类名.class)

字符串锁(比较特别)

应用场景

在多线程下对共享资源的安全操作。

需求:启动5个线程对共享资源total进行安全操作。

同步锁在多线程单例模式下的使用

以上三类同步锁都可以。

package cn.myThread;

public class MyThread implements Runnable {
    private static int total =
10;
    @Override
    public void run() {
        synchronized (this){ //使用this对象锁
        //synchronized (MyThread.class){ //使用MyThread.class类锁
        //synchronized (""){
//使用字符串锁
           
System.out.println(Thread.currentThread().getName()
+ "正在运行");
            try {
                Thread.sleep(100);
            } catch (InterruptedException
e) {
                e.printStackTrace();
            }
            total--;
            System.out.println(total);
            System.out.println(Thread.currentThread().getName()
+ "线程结束");
        }
    }
}

package cn.test;

import cn.myThread.MyThread;

public class TestMyThread {
    public static void main(String[]
args){
        MyThread
myThread = new MyThread();
        Thread thread = null;
        for (int i = 1 ;
i <= 5 ; i++){
            thread = new Thread(myThread,"线程"+i);
//
开启5个线程,传入同一个对象
            thread.start();
        }
    }
}

线程1正在运行

9

线程1线程结束

线程3正在运行

8

线程3线程结束

线程5正在运行

7

线程5线程结束

线程2正在运行

6

线程2线程结束

线程4正在运行

5

线程4线程结束

分析:从运行结果可以看出5个线程串行执行同步锁里面的代码,因为5个线程中的同步锁对象this指向同一个的对象(同步锁对象MyThread.class类锁是同一个对象、同步锁对象 ”” 字符串锁是同一个对象),所以5个线程会串行执行同步锁里面的代码。

同步锁在多线程多例模式下的使用

错误用法

package cn.myThread;

public class MyThread implements Runnable {
    private static int total =
10;
    @Override
    public void run() {
        synchronized (this){//使用this对象锁
           
System.out.println(Thread.currentThread().getName()
+ "正在运行");
            try {
                Thread.sleep(100);
            } catch (InterruptedException
e) {
                e.printStackTrace();
            }
            total--;
            System.out.println(total);
            System.out.println(Thread.currentThread().getName()
+ "线程结束");
        }
    }
}

package cn.test;

import cn.myThread.MyThread;

public class TestMyThread {
    public static void main(String[]
args){
        Thread thread = null;
        for (int i = 1 ; i <= 5 ;
i++){
            thread = new Thread(new MyThread(),"
线程"+i);//开启5个线程,传入5个不同对象
            thread.start();
        }
    }
}

线程2正在运行

线程1正在运行

线程3正在运行

线程5正在运行

线程4正在运行

9

7

9

8

线程1线程结束

线程5线程结束

线程2线程结束

线程3线程结束

6

线程4线程结束

分析:从运行结果可以看出5个线程并行执行同步锁里面的代码,因为5个线程中的同步锁对象this指向5个不同的对象,所以5个线程会同时执行同步锁里面的代码。

正确用法

方式一:

package cn.myThread;

public class MyThread implements Runnable {
    private static int total =
10;
    @Override
    public void run() {
       
synchronized (MyThread.class){//使用MyThread.class类锁
           
System.out.println(Thread.currentThread().getName()
+ "正在运行");
            try {
                Thread.sleep(100);
            } catch (InterruptedException
e) {
                e.printStackTrace();
            }
            total--;
            System.out.println(total);
            System.out.println(Thread.currentThread().getName()
+ "线程结束");
        }
    }
}

package cn.test;

import cn.myThread.MyThread;

public class TestMyThread {
    public static void main(String[]
args){
        Thread thread = null;
        for (int i = 1 ;
i <= 5 ; i++){
            thread = new Thread(new MyThread(),"线程"+i);
//
开启5个线程,传入5个不同对象
            thread.start();
        }
    }
}

线程1正在运行

9

线程1线程结束

线程5正在运行

8

线程5线程结束

线程4正在运行

7

线程4线程结束

线程3正在运行

6

线程3线程结束

线程2正在运行

5

线程2线程结束

分析:从运行结果可以看出5个线程串行执行同步锁里面的代码,因为5个线程中的同步锁对象MyThread.class类锁是同一个对象,所以5个线程会串行执行同步锁里面的代码。

方式二:

package cn.myThread;

public class MyThread implements Runnable {
    private static int total =
10;
    @Override
    public void run() {
       
synchronized (""){//使用字符串锁
            System.out.println(Thread.currentThread().getName()
+ "正在运行");
            try {
                Thread.sleep(100);
            } catch (InterruptedException
e) {
                e.printStackTrace();
            }
            total--;
            System.out.println(total);
            System.out.println(Thread.currentThread().getName()
+ "线程结束");
        }
    }
}

package cn.test;

import cn.myThread.MyThread;

public class TestMyThread {
    public static void main(String[]
args){
        Thread thread = null;
        for (int i = 1 ;
i <= 5 ; i++){
            thread = new Thread(new MyThread(),"线程"+i);
//
开启5个线程,传入5个不同对象
            thread.start();
        }
    }
}

线程1正在运行

9

线程1线程结束

线程4正在运行

8

线程4线程结束

线程5正在运行

7

线程5线程结束

线程3正在运行

6

线程3线程结束

线程2正在运行

5

线程2线程结束

分析:从运行结果可以看出5个线程串行执行同步锁里面的代码,因为5个线程中的同步锁对象 ”” 字符串锁是同一个对象,所以5个线程会串行执行同步锁里面的代码。

java同步锁的正确使用的更多相关文章

  1. Java同步锁——lock与synchronized 的区别【转】

    在网上看来很多关于同步锁的博文,记录下来方便以后阅读 一.Lock和synchronized有以下几点不同: 1)Lock是一个接口,而synchronized是Java中的关键字,synchroni ...

  2. Java同步锁全息详解

    一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...

  3. java 同步锁方法

    方法一:动态同步锁 class Demo_thread implements Runnable{ public static int sum = 0; public synchronized void ...

  4. Java同步锁何时释放?

    在测试java多线程中有关 “生产者和消费者” 这个经典问题的时候,写代码测试的时候,思考到一些问题(所以还是要动手,实践才能储真知啊), synchronize 同步锁何时释放,何时获得?重新获得锁 ...

  5. java同步锁实现方法

    1.synchronized关键字修饰 当用此关键字修饰方法时,     内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就处于阻塞状态 synchronized关键字也可以修饰静态方法,此 ...

  6. JAVA同步锁机制 wait() notify() notifyAll()

    wait() notify() notifyAll() 这3个方法用于协调多个线程对共享数据的存取,所以必须在synchronized语句块中使用. wait() 必须在synchronized函数或 ...

  7. Java Learning:并发中的同步锁(synchronized)

    引言 最近一段时间,实验室已经倾巢出动找实习了,博主也凑合了一把,结果有悲有喜,BAT理所应当的跪了,也收到了其他的offer,总的感受是有必要夯实基础啊. 言归正传,最近在看到java多线程的时候, ...

  8. Redis实现分布式锁的正确使用方式(java版本)

    Redis实现分布式锁的正确使用方式(java版本) 本文使用第三方开源组件Jedis实现Redis客户端,且只考虑Redis服务端单机部署的场景. 分布式锁一般有三种实现方式: 1. 数据库乐观锁: ...

  9. Java多线程简析——Synchronized(同步锁)、Lock以及线程池

    Java多线程 Java中,可运行的程序都是有一个或多个进程组成.进程则是由多个线程组成的.最简单的一个进程,会包括mian线程以及GC线程. 线程的状态 线程状态由以下一张网上图片来说明: 在图中, ...

随机推荐

  1. RAP开发入门-布局管理

    布局类继承关系 FillLayout  new FillLayout(SWT.VERTICAL/HORIZONTAL)设置竖直/水平填充 RowLayout wrap折行显示.pack自适应布局(布局 ...

  2. [转] 利用git钩子,使用python语言获取提交的文件列表

    项目有个需求,需要获取push到远程版本库的文件列表,并对文件进行特定分析.很自然的想到,要利用git钩子来触发一个脚本,实现获取文件列表的功能.比较着急使用该功能,就用python配合一些git命令 ...

  3. JAVA(TOMCAT)远程调试

    当我们的项目部署到远程机器(开发环境和部署环境在不同的jvm下)中,而远程机器的数据和本地有可能不一样,这个时候我们可能需要连接到远程机器进行调试.为了解决这一问题,JAVA为我们提供了Java平台调 ...

  4. caffe学习笔记--跑个SampleCode

    Caffe默认情况会安装在CAFFERROOT,就是解压到那个目录,例如: home/username/caffe-master, 所以下面的工作,默认已经切换到了该工作目录.下面的工作主要是,用于测 ...

  5. type="radio"样式修改

    input[type=radio],input[type=checkbox] { display: inline-block; vertical-align: middle; width: 20px; ...

  6. 快速搭建一个本地的FTP服务器 win10及win7

    快速搭建一个本地的FTP服务器   如果需要开发FTP文件上传下载功能,那么需要在本机上搭建一个本地FTP服务器,方便调试. (win10) 第一步:配置IIS Web服务器 1.1 控制面板中找到“ ...

  7. elasticsearch聚合函数

    计算每个tag下的商品数量 GET /ecommerce/product/_search { "aggs": {  //聚合 "group_by_tags": ...

  8. 小白学习Spark系列三:RDD常用方法总结

    上一节简单介绍了Spark的基本原理以及如何调用spark进行打包一个独立应用,那么这节我们来学习下在spark中如何编程,同样先抛出以下几个问题. Spark支持的数据集,如何理解? Spark编程 ...

  9. 阿里云服务上面部署redis + 本地Redis客户端连接方法

    本文结合自己在阿里云服务器上面搭建redis服务器,在本地redis的客户端Redis Desktop Manager连接成功的操作,将操作中的一些方法做了一些归纳和总结,希望可以帮到有需要的同学. ...

  10. Linux设备驱动--块设备(三)之程序设计(转)

    http://blog.csdn.net/jianchi88/article/details/7212701 块设备驱动注册与注销 块设备驱动中的第1个工作通常是注册它们自己到内核,完成这个任务的函数 ...