并发编程(5):锁对象、同步代码块

1、同步代码块

使用synchronized声明的方法在某些情况下是有弊端的,比如A线程调用同步的方法执行一个很长时间的任务,那么B线程就必须等待比较长的时间才能执行,这样的情况下可以使用synchronized代码块去优化代码执行时间,也就是通常所说的减小锁的粒度。

代码

public class Demo7 {
	public void doLongTimeTask(){
		try {

			System.out.println("当前线程开始:" + Thread.currentThread().getName() + 
					", 正在执行一个较长时间的业务操作,其内容不需要同步");
			Thread.sleep(2000);

			synchronized(this){
				System.out.println("当前线程:" + Thread.currentThread().getName() + 
					", 执行同步代码块,对其同步变量进行操作");
				Thread.sleep(1000);
			}
			System.out.println("当前线程结束:" + Thread.currentThread().getName() +
					", 执行完毕");

		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		final Demo7 demo7 = new Demo7();
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				demo7.doLongTimeTask();
			}
		},"t1");
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				demo7.doLongTimeTask();
			}
		},"t2");
		t1.start();
		t2.start();
	}
}

效果:

2、synchronized可以使用任意的Object进行加锁

public class ObjectLock {

	public void method1(){
		synchronized (this) {	// 对象锁
			try {
				System.out.println("do method1..");
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public void method2(){		// 类锁
		synchronized (ObjectLock.class) {
			try {
				System.out.println("do method2..");
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private Object lock = new Object();
	public void method3(){		// 任何对象锁
		synchronized (lock) {
			try {
				System.out.println("do method3..");
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {

		final ObjectLock objLock = new ObjectLock();
		new Thread(new Runnable() {
			@Override
			public void run() {
				objLock.method1();
			}
		}, "t1").start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				objLock.method2();
			}
		}, "t2").start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				objLock.method3();
			}
		}, "t3").start();
	}
}

效果:

说明:这里结果同时打印的。

另外特别注意,就是不要使用String的常量加锁,会出现死循环问题

3、锁对象的改变问题

当使用一个对象进行加锁的时候,要注意对象本身发生改变的时候,那么持有的锁就不同。如果对象本身不发生改变,那么依然是同步的,即使是对象的属性值发生了改变。

注意:同一对象属性的修改不会影响锁的情况

时间: 2024-08-05 19:13:50

并发编程(5):锁对象、同步代码块的相关文章

[java多线程] - 锁机制&同步代码块&信号量

在美眉图片下载demo中,我们可以看到多个线程在公用一些变量,这个时候难免会发生冲突.冲突并不可怕,可怕的是当多线程的情况下,你没法控制冲突.按照我的理解在java中实现同步的方式分为三种,分别是:同步代码块机制,锁机制,信号量机制. 一.同步代码块 在java的多线程并发开发过程中,我们最常用的方式就是使用同步代码关键字(synchronized).这种方式的使用不是特别复杂,需要注意的只是你需要明确到底同步的是那个对象,只有当同步的对象一致的情况下,才能够控制互斥的操作.一般情况下,我们会同

JAVA高并发程序设计学习:Synchronized同步代码块具体使用方法

多线程同时对资源进行访问时,同步机制使得同一时间内只能有一个线程对资源进行操作. 同步机制可以用Synchronized实现. 当Synchronized修饰一个方法的时候,该方法称为同步方法. 当Synchronized方法执行完成或者异常时会释放锁. 会有同学对synchronized修饰方法,静态方法,对象时具体对哪些东西加锁不是很明白,这里会进行详细的讲解. synchronized修饰方法时,会对类实例进行加锁,该实例的所有synchronized方法必须等当前锁释放后才能访问. sy

使用synchronized(非this对象)同步代码块解决脏读问题

首先通过示例来学习验证多个线程调用同一个方法时随机的. package syn_out_asyn; import java.util.ArrayList; import java.util.List; /** * Created by Administrator on 2017/1/19 0019. */ public class MyList { private List list = new ArrayList(); synchronized public void add(String u

java同步代码块

/** abc三个售票窗口,售50张票. 需求:可以做到同时销售,且不能卖重叠的,以及不能超过50 同步代码块 synchronized(对象){     同步代码块: } 对象如同锁,持有锁的线程可以在同步中执行 没有持有锁的线程即使获得CPU的执行器,也无法执行. 同步前提: 1.多线程的代码块才需要同步,即run里的代码才需要加同步.对共享数据加同步 2.必须是多个线程使用同一个锁,才需要同步 好处:提高多线程的安全问题 弊端:多个线程需要判断锁,较为消耗资源 */ class Tickt

day23--电影院买票问题解决 同步代码块 同步方法 静态同步方法的引入

package cn.itcast_11; /* * A:同步代码块的锁对象是谁呢? *         任意对象. *  * B:同步方法的格式及锁对象问题? *         把同步关键字加在方法上. *  *         同步方法的锁是谁呢? *             this(一个类本身对象就是this) *  * C:静态方法及锁对象问题? *         静态方法的锁对象是谁呢? *             类的字节码文件对象.(反射会讲) */public class

java的同步方法和同步代码块,对象锁,类锁区别

/** * @author admin * @date 2018/1/12 9:48 * 作用在同一个实例对象上讨论 * synchronized同步方法的测试 * 两个线程,一个线程调用synchronized修饰方法,另一个线程可以调用非synchronized修饰的方法,互不影响 */ public class SynchronizedTest { public synchronized void methodA() { try { for (int i = 0; i < 5; i++)

JAVA之旅(十三)——线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this

JAVA之旅(十三)--线程的安全性,synchronized关键字,多线程同步代码块,同步函数,同步函数的锁是this 我们继续上个篇幅接着讲线程的知识点 一.线程的安全性 当我们开启四个窗口(线程)把票陆陆续续的卖完了之后,我们要反思一下,这里面有没有安全隐患呢?在实际情况中,这种事情我们是必须要去考虑安全问题的,那我们模拟一下错误 package com.lgl.hellojava; import javax.security.auth.callback.TextInputCallback

Java并发学习之十四——使用Lock同步代码块

本文是学习网络上的文章时的总结,感谢大家无私的分享. Java提供另外的机制用来同步代码块.它比synchronized关键字更加强大.灵活.Lock 接口比synchronized关键字提供更多额外的功能.在使用Lock时需要注意的是要释放Lock锁. package chapter2; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /* * 打印队列 */ pu

Android(java)学习笔记68:同步代码块的锁和同步方法的应用

1 package cn.itcast_11; 2 3 public class SellTicket implements Runnable { 4 5 // 定义100张票 6 private static int tickets = 100; 7 8 // 定义同一把锁 9 private Object obj = new Object(); 10 private Demo d = new Demo(); 11 12 private int x = 0; 13 14 //同步代码块用obj