同步锁分类

对象锁(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. Wireshark抓包过滤

    主要说明下抓包前准备工作,及wireshark里面的两个过滤器:捕获过滤器和应用显示过滤器 1.捕获过滤器.顾名思义就是捕获时的过滤器.主要用来决定你要抓包抓哪个IP哪个端口,明确自己要抓哪个IP和端 ...

  2. Python框架、库和软件资源大全(整理篇)

    有少量修改,请访问原始链接.PythonWIn的exe安装包;http://www.lfd.uci.edu/~gohlke/pythonlibs/ 原文链接:codecloud.net/python- ...

  3. Installshield下如何在指定目录执行bat

    在做InstallShield中碰到这样的问题,有service.bat需要在指定的一个目录运行. 一开始在bat内写入语句: cd d:\XXXXX command1.exe command2.ex ...

  4. 创建一个dynamics CRM workflow (六) - Debugging Custom Workflows

    我们也deploy部署了custom workflows, debugging是开发当中不可或缺的一个步骤. debug workflow的步骤和debug有些许不一样: 1. install pro ...

  5. selenium的显示等待和隐式等待区别

    1.selenium的显示等待 原理:显式等待,就是明确的要等到某个元素的出现或者是某个元素的可点击等条件,等不到,就一直等,除非在规定的时间之内都没找到,那么就跳出Exception.(简而言之:就 ...

  6. 51nod-活动安排问题

    有若干个活动,第i个开始时间和结束时间是[Si,fi),只有一个教室,活动之间不能交叠,求最多安排多少个活动?分析: 我们就是想提高教室地利用率,尽可能多地安排活动.考虑容易想到的几种贪心策略: (1 ...

  7. Linux菜鸟成长日记 ( Linux 下的 ftp 文件传输协议 )

    https://blog.csdn.net/buster_zr/article/details/80244542 FTP FTP 是 File Transfer Protocol (文件传输协议)的英 ...

  8. java 比较两个时间大小

    Date d1 = new Date(System.currentTimeMillis()-1000); Date d2 = new Date(System.currentTimeMillis()); ...

  9. 1.2 为Eclipse绑定Tomcat

    1.window→preferences打开属性窗口 2.点击add 3.点击Tomcat6.0 点击next 4.选择tomcat的解压目录和jdk,并点击finish 5.点击ok 6.打开ser ...

  10. github插件

    可能是迄今为止最好的GitHub代码浏览插件,基本实现浏览器变成代码阅读器,支持目录列表,交叉索引等功能: O网页链接 ​​​​ http://weibo.com/1963193953/Fdj2cFQ ...