聊聊synchronized的锁问题

本文不会特别深入细致地讨论synchronized,只是做一个通俗易懂的说明,以及看清一类问题的本质,希望能给大家一点启发。

问题描述

有一个类A,提供了三个方法。分别是静态同步方法,非静态同步方法,含有静态代码块的方法

 1 class A{
 2     public static synchronized void print1(){
 3         print();
 4     }
 5     public synchronized void print2(){
 6         print();
 7     }
 8     public void print3(){
 9         synchronized (new Object()){
10             print();
11         }
12     }
13     private static void print(){
14         while(true){
15             String threadName = Thread.currentThread().getName();
16             System.out.println(threadName);
17         }
18     }
19 }

请回答一下四种情况的输出结果

 1 class Test {
 2     // 1.两个线程,同一个类,调用静态同步方法print1
 3     @Test
 4     public void test1() {
 5         Thread thread1 = new Thread(() -> A.print1());
 6         Thread thread2 = new Thread(() -> A.print1());
 7         thread1.start();
 8         thread2.start();
 9     }
10     // 2.两个线程,同一个对象,调用非静态同步方法print2
11     @Test
12     public void test2() {
13         A a = new A();
14         Thread thread1 = new Thread(() -> a.print2());
15         Thread thread2 = new Thread(() -> a.print2());
16         thread1.start();
17         thread2.start();
18     }
19     // 3.两个线程,不同对象,调用非静态同步方法print2
20     @Test
21     public void test3() {
22         Thread thread1 = new Thread(() -> new A().print2());
23         Thread thread2 = new Thread(() -> new A().print2());
24         thread1.start();
25         thread2.start();
26     }
27     // 4.两个线程,同一个对象,调用普通非静态方法(带有同步代码块)print3
28     @Test
29     public void test4() {
30         A a = new A();
31         Thread thread1 = new Thread(() -> a.print3());
32         Thread thread2 = new Thread(() -> a.print3());
33         thread1.start();
34         thread2.start();
35     }
36 }

问题答案

先直接报上答案:

  1. 一直输出“Thread-1”
  2. 一直输出“Thread-1”
  3. 交替输出“Thread-1”和“Thread-2”
  4. 交替输出“Thread-1”和“Thread-2”

问题本质分析

不废话,直接点出,这四个问题只要明白两件事即可:

  • 一个线程是否能执行被同步了的方法,主要看是否能拿到锁对象
  • 静态方法的同步锁是类对象本身,非静态方法的同步锁是实例对象本身,同步代码块的同步锁是括号中传入的对象

所以

  • 如果两个线程执行方法用到了同一个锁对象,则一个线程执行时,另一个线程必须等待其释放锁才能拿到锁,所以此时两个线程会互斥

所以

  • 1中两个线程执行方法的锁对象都是类对象A,所以线程之间互斥
  • 2中两个线程执行方法的锁对象都是实例对象a,所以线程之间互斥
  • 3中两个线程执行方法的锁对象分别是new出来的两个实例对象a,所以线程互不影响
  • 4中两个线程执行方法的锁对象分别是new出来的两个实例对象object,所以线程互不影响

Game Over

时间: 2024-10-13 05:47:52

聊聊synchronized的锁问题的相关文章

java synchronized究竟锁住的是什么

刚学java的时候,仅仅知道synchronized一个线程锁.能够锁住代码,可是它真的能像我想的那样,能够锁住代码吗? 在讨论之前先看一下项目中常见关于synchronized的使用方法: public synchronized void syncCurrentObject() { System.out.println(Thread.currentThread().getName()+"..start.."+"-----"+System.currentTimeMi

synchronized的锁是针对多线程的

synchronized的锁是针对多线程的,从线程的角度去思考才能真正弄明白. Java的synchronized使用方法总结 1. 把synchronized当作函数修饰符时 这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象.也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果.但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法. 同步块,示例代码

Java多线程之synchronized线程锁

1 package org.study2.javabase.ThreadsDemo.sync; 2 3 /** 4 * @Auther:GongXingRui 5 * @Date:2018/9/18 6 * @Description:synchronized线程锁 7 **/ 8 public class TicketApp { 9 public static void main(String args[]) { 10 Ticket ticket = new Ticket(); 11 Threa

synchronized互斥锁实例解析

目录 synchronized互斥锁实例解析 1.互斥锁基础使用:防止多个线程访问对象的synchronized方法. 1.1.不加互斥锁时 1.2.加互斥锁后 2.脏读 2.1.不加锁 2.2.加锁后 java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途径就是进入这个锁的保护的同步代码块或方法. java内置锁是一个互斥锁. 对象锁是用于对象实例方法,或者一个对象实例

Synchronized到底锁住的是谁?

先来一道并发编程笔试题 题目:利用5个线程并发执行,num数字累计计数到10000,并打印. /** * Description: * 利用5个线程并发执行,num数字累加计数到10000,并打印. * 2019-06-13 * Created with OKevin. */ public class Count { private int num = 0; public static void main(String[] args) throws InterruptedException {

JAVA synchronized关键字锁机制(中)

synchronized 锁机制简单的用法,高效的执行效率使成为解决线程安全的首选. 下面总结其特性以及使用技巧,加深对其理解. 特性: 1. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.       2. 当一个线程同时访问object的一个synchronized(this)同步代码块时,其它线程仍然可以访问非修饰的方法或代码块.       3. 当多个线程同时访问object的synchronized(this)同步代码

2.synchronized同步锁

原文链接:http://blog.csdn.net/zteny/article/details/54863391 简介 synchronized是Java语言的一个关键字,用来修饰一个方法或者代码块,使得目标达到线程同步的目的. 当我们希望某个方法或者代码块,同一时间只能有一个线程能够执行,即是同一时间只有一个线程能够进入该方法或者代码块,其它线程将会被阻塞直接原线程执行结束,此时我们使用该关键字. 用法 由上面的简介可以可得synchronized的两种用法,如下: public synchr

悲观的并发策略——Synchronized互斥锁

volatile既然不足以保证数据同步,那么就必须要引入锁来确保.互斥锁是最常见的同步手段,在并发过程中,当多条线程对同一个共享数据竞争时,它保证共享数据同一时刻只能被一条线程使用,其他线程只有等到锁释放后才能重新进行竞争.对于java开发人员,我们最熟悉的肯定就是用synchronized关键词完成锁功能,在涉及到多线程并发时,对于一些变量,你应该会毫不犹豫地加上synchronized去保证变量的同步性. 在C/C++可直接使用操作系统提供的互斥锁实现同步和线程的阻塞和唤起,与之不同的是,j

synchronized同步锁详解

1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法.如:  public synchronized void accessVal(int newVal);  synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能 执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新