一、多个对象多把锁

例子代码:

package com.lhy.thread01;

public class MultiThread {

    //static
private int num = 0; //加上static后就是类级别的锁。不加,是对象级别的锁,此时多个线程之间是互不干扰
public synchronized void printNum(String tag){
try{
if("a".equals(tag)){
num = 100;
System.out.println("tag a ,set num over!");
Thread.sleep(1000);//a会睡1秒,b不会
}else{
num = 200;
System.out.println("tag b ,set num over!");
}
System.out.println("tag "+ tag +" , num = "+ num);
}catch(Exception e){
e.printStackTrace();
}
} public static void main(String[] args) {
//两个不同的对象
final MultiThread m1 = new MultiThread();
final MultiThread m2 = new MultiThread(); Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m1.printNum("a");
}
}); Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
m2.printNum("b");
}
}); t1.start();
t2.start();
} }

执行结果:

关键字synchornized获得的锁是对象锁,哪个线程先执行synchornized关键字的方法,哪个线程就持有该方法所属对象的锁,例子程序中,由于m1和m2是两个不同的对象,t1 线程获得 m1对象的锁,t2线程获得m2对象的锁,所以互不影响。

验证, 如果将main方法改为如下所示,t1 和 t2 线程都执行m1对象的printNum方法,此时两个线程在抢一把锁,所以执行会按顺序来:

public static void main(String[] args) {
//两个不同的对象
final MultiThread m1 = new MultiThread();
//final MultiThread m2 = new MultiThread(); Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m1.printNum("a");
}
}); Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
m1.printNum("b");
}
}); t1.start();
t2.start();
}

二、多个对象一把锁(类锁)

在静态方法上加上synchornized关键字,表示锁定.class类,类一级别的锁(独占.class 类)

例子程序:

public class MultiThread {

    //static
private static int num = 0; //加上static后就是类级别的锁。不加,是对象级别的锁,此时多个线程之间是互不干扰
public static synchronized void printNum(String tag){
try{
if("a".equals(tag)){
num = 100;
System.err.println("tag a ,set num over!");
Thread.sleep(1000);//a会睡1秒,b不会
}else{
num = 200;
System.err.println("tag b ,set num over!");
}
System.err.println("tag "+ tag +" , num = "+ num);
}catch(Exception e){
e.printStackTrace();
}
} public static void main(String[] args) {
//两个不同的对象
final MultiThread m1 = new MultiThread();
final MultiThread m2 = new MultiThread(); Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
m1.printNum("a");
}
}); Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
m2.printNum("b");
}
}); t1.start();
t2.start();
} }

执行结果:

是按照t1、t2 顺序执行的。

线程安全-002-多个线程多把锁&类锁的更多相关文章

  1. Android线程管理之ThreadPoolExecutor自定义线程池

    前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己 ...

  2. 【转】线程及同步的性能 - 线程池 / ThreadPoolExecutors / ForkJoinPool

    线程池和ThreadPoolExecutors 虽然在程序中可以直接使用Thread类型来进行线程操作,但是更多的情况是使用线程池,尤其是在Java EE应用服务器中,一般会使用若干个线程池来处理来自 ...

  3. java多线程系类:JUC线程池:05之线程池原理(四)(转)

    概要 本章介绍线程池的拒绝策略.内容包括:拒绝策略介绍拒绝策略对比和示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html 拒绝策略 ...

  4. java多线程系类:JUC线程池:03之线程池原理(二)(转)

    概要 在前面一章"Java多线程系列--"JUC线程池"02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包 ...

  5. java多线程系类:JUC线程池:02之线程池原理(一)

    在上一章"Java多线程系列--"JUC线程池"01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我 ...

  6. java多线程系类:JUC线程池:01之线程池架构

    概要 前面分别介绍了"Java多线程基础"."JUC原子类"和"JUC锁".本章介绍JUC的最后一部分的内容--线程池.内容包括:线程池架构 ...

  7. iOS开发:(线程篇-上)线程和进程

    iOS开发多线程篇—多线程简单介绍 一.进程和线程 1.什么是进程 进程是指在系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内 比如同时打开QQ.Xcod ...

  8. java 22 - 18 多线程之 线程的状态转换、线程组

    线程的状态转换图解:图片 线程的线程组: 线程组: 把多个线程组合到一起.    它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制. 首先创建一个Runnable的实现类 publi ...

  9. 突破python缺陷,实现几种自定义线程池 以及进程、线程、协程的介绍

    Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. #!/usr/bin/env python # -*- coding:utf-8 -*- import t ...

随机推荐

  1. 【转】Appium 优化版

    Appium 开源分享优化版 之前分享过PageObject+Python+Appium 本版本是对上次版本较大改版,主要解决了: 失败重连一次(默认一次)可配置多次 基于appium1.7.1 ui ...

  2. Annotation 标注

    1.画出基本图 当图线中某些特殊地方需要标注时,我们可以使用 annotation. matplotlib 中的 annotation 有两种方法, 一种是用 plt 里面的 annotate,一种是 ...

  3. Html5学习笔记:图片上传

    图片上传是业务需求中常见的功能,最基础的是单图片的上传.比较复杂的多图片上传,都是基于单图片上传. Form表单上传 h5的原生表单上传图片,代码如下: <!DOCTYPE html> & ...

  4. Linux - rename 批量替换两种模式

    模式一: rename  sub raw  * 模式二: rename  's/sub/raw/g' * sub raw 这里支持一定程序的正则匹配

  5. ibatis (六) dynamic的用法

    view plain copy print? dynamic可以去除第一个prepend="and"中的字符(这里为and),从而可以帮助你实现一些很实用的功能.具体情况如下: 1 ...

  6. 20175316 盛茂淞 2018-2019-2 《Java程序设计》实验一 Java开发环境的熟悉 实验报告

    20175316 盛茂淞 2018-2019-2 <Java程序设计>实验一 Java开发环境的熟悉 实验报告 一.实验要求 1.使用JDK编译.运行简单的Java程序: 2.使用IDEA ...

  7. Java输入输出流详解

    通过数据流.序列化和文件系统提供系统输入和输出. Java把这些不同来源和目标的数据都统一抽象为数据流.Java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为 ...

  8. bgfx入门练习1——切换图形API驱动模式DX与OpenGL

    翻了下上次编译bgfx是去年2月份的事了,最近正好想试试DX,OpenGL双驱动,看Urho3D和Klayge光封装就头痛,人又懒,写OpenGL时也基本glfw,于是想到bgfx,不如再试试. 发现 ...

  9. nginx启动或者重启失败,报错nginx: [error] open() "/usr/local/var/run/nginx.pid" failed (2: No such file or directory)

    第一种方案: 1. 执行命令 :open /usr/local/etc/nginx 打开nginx安装目录 nginx安装目录默认位置有:(找到适合你的) /etc/nginx/nginx.conf, ...

  10. php,mysql存储过程的简单例子

    一.连接mysql 使用phpmyadmin: 打开test数据库: 二.创建存储过程 参数如图. 三.php中调用存储过程 <?php $user = "root"; // ...