Java多线程之synchronized(五)
上篇介绍了用synchronized修饰static方式来实现“Class 锁”,今天要介绍另一种实现方式,synchronized(class)代码块,写法不一样但是作用是一样的。下面我附上一段代码来看一下synchronized(class)代码块的基本用法,如下:
public static void main(String[] args) {
Service4 s1 = new Service4();
Service4 s2 = new Service4();
ThreadA a = new ThreadA(s1);
ThreadB b = new ThreadB(s2);
a.setName("A");
b.setName("B");
a.start();
b.start();
}
public static class ThreadA extends Thread {
private Service4 service;
public ThreadA(Service4 service) {
super();
this.service = service;
}
@Override
public void run() {
super.run();
service.printA();
}
}
public static class ThreadB extends Thread {
private Service4 service;
public ThreadB(Service4 service) {
super();
this.service = service;
}
@Override
public void run() {
super.run();
service.printB();
}
}
}
class Service4 {
static public void printA() {
synchronized (Service4.class) {
try {
System.out.println("线程:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printA");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static public void printB() {
synchronized (Service4.class) {
System.out.println("线程:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
}
}
}
运行结果如下:synchronized(class)代码块的作用和synchronized static的作用是一样的

以前我说过,synchronized还可以传入其他的实例对象或者方法的形参,那么我现在要说一种把synchronized(class)和String一起使用的特殊情况,还是用代码讲解,下面我附上一段代码,如下:
public static void main(String[] args) {
Service5 service = new Service5();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
}
public static class ThreadB extends Thread {
private Service5 service;
public ThreadB(Service5 service) {
super();
this.service = service;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
service.print("AA");
}
}
public static class ThreadA extends Thread {
private Service5 service;
public ThreadA(Service5 service) {
super();
this.service = service;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
service.print("AA");
}
}
}
class Service5 {
public static void print(String string) {
try {
synchronized (string) {
while (true) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果如下:可以看到输出结果会打印出无数个连续的A,这是由于在JVM中有String常量池缓存的功能,所以说printA()和printB()两个方法里传进来的“AA”是同一个值,因此两个线程持有相同的锁,所以总有一个线程执行不到。

上面已经看到了常量池带来的问题,因此大多情况下,都不用String最为对像锁,而改用其他的,比如new Object()实例化一个Object对象。可以看看下面的例子,运行后的区别在哪,如下:
public static void main(String[] args) {
Service6 service = new Service6();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
}
public static class ThreadB extends Thread {
private Service6 service;
public ThreadB(Service6 service) {
super();
this.service = service;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
service.print(new Object());
}
}
public static class ThreadA extends Thread {
private Service6 service;
public ThreadA(Service6 service) {
super();
this.service = service;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
service.print(new Object());
}
}
}
class Service6 {
public static void print(Object object) {
try {
synchronized (object) {
while (true) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果如下:可以看到运行结果是交叉的异步的,说明两个线程持有的锁不是同一把锁。

Java多线程之synchronized(五)的更多相关文章
- JAVA多线程之Synchronized关键字--对象锁的特点
一,介绍 本文介绍JAVA多线程中的synchronized关键字作为对象锁的一些知识点. 所谓对象锁,就是就是synchronized 给某个对象 加锁.关于 对象锁 可参考:这篇文章 二,分析 s ...
- (二)java多线程之synchronized
本人邮箱: kco1989@qq.com 欢迎转载,转载请注明网址 http://blog.csdn.net/tianshi_kco github: https://github.com/kco198 ...
- JAVA多线程之Synchronized、wait、notify实例讲解
一.Synchronized synchronized中文解释是同步,那么什么是同步呢,解释就是程序中用于控制不同线程间操作发生相对顺序的机制,通俗来讲就是2点,第一要有多线程,第二当多个线程同时竞争 ...
- Java多线程之synchronized(四)
前面几章都是在说synchronized用于对象锁,无论是修饰方法也好修饰代码块也好,然而关键字synchronized还可以应用到static静态方法上,如果这样写,那就是对当前的*.java文件所 ...
- Java多线程之synchronized(三)
在多线程访问同一个对象中的不同的synchronized方法或synchronized代码块的前提下,也就是“对象监控器”为同一个对象的时候,也就是synchronized的锁为同一把锁的时候,调用的 ...
- Java多线程之synchronized及其优化
Synchronized和同步阻塞synchronized是jvm提供的同步和锁机制,与之对应的是jdk层面的J.U.C提供的基于AbstractQueuedSynchronizer的并发组件.syn ...
- JAVA多线程之synchronized和volatile实例讲解
在多线程中,提到线程安全.线程同步,我们经常会想到两个关键字:volatile和synchronized,那么这两者有什么区别呢? 1. volatile修饰的变量具有可见性 volatile是变量修 ...
- java 多线程之synchronized wait/notify解决买票问题
一.Java线程具有五中基本状态 新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread(); 就绪状态(Runnable):当调用线程对象的st ...
- Java多线程之synchronized和volatile
概述 用Java来开发多线程程序变得越来越常见,虽然Java提供了并发包来简化多线程程序的编写,但是我们有必要深入研究一下,才能更好的掌握这块知识. 本文主要对Java提供的底层原语synchroni ...
随机推荐
- JS表格排序
var employees = [] employees[0] = { name: "George", age: 32, retiredate: "March 12, 2 ...
- Radio Checkbox Select 操作
一个小总结 <!DOCTYPE html> <html> <head> <meta name="description" content= ...
- 关于mysqli 连接数不能正确释放的解决方案
/** * 析构函数 */ //解决重复链接的问题 private $db_handler = null; function __destruct() { Log::logWrite($this-&g ...
- UIWindow 详解
UIWindow对象是所有UIView的根视图,管理和协调的应用程序的显示.分发事件给View.UIWindow类是UIView的子类,可以看作是特殊的UIView.一般应用程序只有一个UIWindo ...
- 精通 VC++ 实效编程280例 - 01 窗口
窗口是屏幕上的一个矩形区域.窗口分为3种:重叠窗口.弹出窗口和子窗口.每个窗口都有由系统绘制的“非客户区”和应用程序绘制的“客户区”.在 MFC 中,CWnd 类为各种窗口提供了基类. 1 通过 HW ...
- Android 新兴的UI模式——侧边导航栏【转】
侧边导航栏也就是大家熟知的SliddingMenu,英文也叫Fly-In App Menu.Side Navigation等.当然谷歌现在已经推出类似这个效果的组件--Navigation Drawe ...
- [cocos2dx笔记015]关于cocos2dx Button三种状态说明
经过几天的填坑,最终将现有的项目由cocos2dx 2.2.2移到cocos2dx 3.2,差点放弃3.2了,但在最后一刻,又把坑填平了. cocos2dx 2.x到3.x是一个巨大的变化,能够算是全 ...
- 虎记:强大的nth-child(n)伪类选择器玩法
写在前面的戏: 最近参加了度娘前端IFE的春季班,刷任务,百度真是有营销头脑,让咱们这帮未来的技术狂人为他到处打广告(我可不去哪),其中做的几个任务中有几个以前没有用到的东西, 也算是有些许收获(现在 ...
- [Jobdu] 题目1517:链表中倒数第k个结点
给出一个链表的头指针,要求找到倒数第k个节点,并输出这个节点的值 例子: 先看一个例子,链表为:1 2 3 4 5 6,倒数第2个节点就是5,倒数第一个节点就是6,以此类推.这里的链表有头节点,就是说 ...
- js函数变量
局部 JavaScript 变量 在 JavaScript 函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它.(该变量的作用域是局部的). 您可以在不同的函数中使用名称相同的局部 ...