`
dreamoftch
  • 浏览: 498331 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

使用synchronized和Lock对象获取对象锁

阅读更多

 Java:使用synchronized和Lock对象获取对象锁

 

 

下面使用ReentrantLock这个锁来实现加锁功能:

 

 

package com.tch.test.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SynchronizedTest {

	private ExecutorService pool = Executors.newFixedThreadPool(4);
	private Lock lock = new ReentrantLock();
	
	public static void main(String[] args) {
		new SynchronizedTest().test();
	}
	
	public void test() {
		Runnable runnable = null;
		for(int i=0;i<4;i++){
			runnable = new Runnable(){
				public void run(){
					while(true){
						execute();
					}
				}
			};
			pool.execute(runnable);
		}
	}
	void execute(){
		lock.lock();//首先获得锁
		try{
			System.out.println(Thread.currentThread().getId()+"获得了lock,开始休息");
			Thread.sleep(300);
		}catch(Exception e){}
		finally{
			System.out.println(Thread.currentThread().getId()+"释放了lock,结束休息");
			lock.unlock();//最后一定要释放锁
		}
	}
}

 

 

然后使用java的synchronized关键字实现加锁:

 

 

package com.tch.test.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SynchronizedTest {

	private ExecutorService pool = Executors.newFixedThreadPool(4);
	//private Lock lock = new ReentrantLock();
	private Object obj = new Object();
	
	public static void main(String[] args) {
		new SynchronizedTest().test();
	}
	
	public void test() {
		Runnable runnable = null;
		for(int i=0;i<4;i++){
			runnable = new Runnable(){
				public void run(){
					while(true){
						execute();
					}
				}
			};
			pool.execute(runnable);
		}
	}
	void execute(){
		synchronized(obj){
			try {
				System.out.println(Thread.currentThread().getId()+"获得了obj的锁,开始休息");
				Thread.sleep(300);
				System.out.println(Thread.currentThread().getId()+"释放了obj的锁,结束休息");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

 

 

 

 

 

在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制。
1.对象的锁
所有对象都自动含有单一的锁。
JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上获得锁时,计数会递增。
只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁。
每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被完全释放,此时别的任务就可以使用此资源。
2.synchronized同步块
2.1同步到单一对象锁
当使用同步块时,如果方法下的同步块都同步到一个对象上的锁,则所有的任务(线程)只能互斥的进入这些同步块。
Resource1.java演示了三个线程(包括main线程)试图进入某个类的三个不同的方法的同步块中,虽然这些同步块处在不同的方法中,但由于是同步到同一个对象(当前对象 synchronized (this)),所以对它们的方法依然是互斥的。
Resource1.java
package com.zj.lock;
import java.util.concurrent.TimeUnit;
 
public class Resource1 {
    public void f() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in f()");
       synchronized (this) {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in f()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       }
    }
 
    public void g() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in g()");
       synchronized (this) {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in g()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       }
    }
 
    public void h() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in h()");
       synchronized (this) {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in h()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       }
    }
 
    public static void main(String[] args) {
       final Resource1 rs = new Resource1();
 
       new Thread() {
           public void run() {
              rs.f();
           }
       }.start();
 
       new Thread() {
           public void run() {
              rs.g();
           }
       }.start();
 
       rs.h();
    }
}
结果:
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
Thread-1:not synchronized in g()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
2.2 同步到多个对象锁
Resource1.java演示了三个线程(包括main线程)试图进入某个类的三个不同的方法的同步块中,这些同步块处在不同的方法中,并且是同步到三个不同的对象(synchronized (this)synchronized(syncObject1)synchronized (syncObject2)),所以对它们的方法中的临界资源访问是独立的。
Resource2.java
package com.zj.lock;
import java.util.concurrent.TimeUnit;
 
public class Resource2 {
    private Object syncObject1 = new Object();
    private Object syncObject2 = new Object();
 
    public void f() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in f()");
       synchronized (this) {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in f()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       }
    }
 
    public void g() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in g()");
       synchronized (syncObject1) {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in g()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       }
    }
 
    public void h() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in h()");
       synchronized (syncObject2) {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in h()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       }
    }
 
    public static void main(String[] args) {
       final Resource2 rs = new Resource2();
 
       new Thread() {
           public void run() {
              rs.f();
           }
       }.start();
 
       new Thread() {
           public void run() {
              rs.g();
           }
       }.start();
 
       rs.h();
    }
}
结果:
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
main:synchronized in h()
Thread-1:not synchronized in g()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
3.Lock对象锁
除了使用synchronized外,还可以使用Lock对象来创建临界区。Resource3.java的演示效果同Resource1.javaResource4.java的演示效果同Resource2.java
Resource3.java
package com.zj.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
public class Resource3 {
    private Lock lock = new ReentrantLock();
 
    public void f() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in f()");
       lock.lock();
       try {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in f()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       finally {
           lock.unlock();
       }
    }
 
    public void g() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in g()");
       lock.lock();
       try {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in g()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       finally {
           lock.unlock();
       }
    }
 
    public void h() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in h()");
       lock.lock();
       try {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in h()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       finally {
           lock.unlock();
       }
    }
 
    public static void main(String[] args) {
       final Resource3 rs = new Resource3();
 
       new Thread() {
           public void run() {
              rs.f();
           }
       }.start();
 
       new Thread() {
           public void run() {
              rs.g();
           }
       }.start();
 
       rs.h();
    }
}
结果:
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
Thread-1:not synchronized in g()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
Thread-0:synchronized in f()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Thread-1:synchronized in g()
Resource4.java
package com.zj.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
public class Resource4 {
    private Lock lock1 = new ReentrantLock();
    private Lock lock2 = new ReentrantLock();
    private Lock lock3 = new ReentrantLock();
 
    public void f() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in f()");
       lock1.lock();
       try {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in f()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       finally {
           lock1.unlock();
       }
    }
 
    public void g() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in g()");
       lock2.lock();
       try {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in g()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       finally {
           lock2.unlock();
       }
    }
 
    public void h() {
       // other operations should not be locked...
       System.out.println(Thread.currentThread().getName()
              ":not synchronized in h()");
       lock3.lock();
       try {
           for (int i = 0; i < 5; i++) {
              System.out.println(Thread.currentThread().getName()
                     ":synchronized in h()");
              try {
                  TimeUnit.SECONDS.sleep(3);
              catch (InterruptedException e) {
                  e.printStackTrace();
              }
           }
       finally {
           lock3.unlock();
       }
    }
 
    public static void main(String[] args) {
       final Resource4 rs = new Resource4();
 
       new Thread() {
           public void run() {
              rs.f();
           }
       }.start();
 
       new Thread() {
           public void run() {
              rs.g();
           }
       }.start();
 
       rs.h();
    }
}
结果:
Thread-0:not synchronized in f()
Thread-0:synchronized in f()
main:not synchronized in h()
main:synchronized in h()
Thread-1:not synchronized in g()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()
Thread-0:synchronized in f()
main:synchronized in h()
Thread-1:synchronized in g()

 

分享到:
评论

相关推荐

    Synchronized 和 Lock 的区别和使用场景

    本文将深入探讨两种主要的锁机制:`synchronized`关键字和`Lock`接口,以及它们各自的特点、应用场景和使用方式。 一、Synchronized `synchronized`是Java中的一个内置关键字,用于提供线程安全。它的主要作用是...

    synchronized枷锁实例

    对象锁是针对类的实例对象而言的,当一个线程访问某个对象的非静态 synchronized 方法或同步代码块时,会获取到该对象的锁。这种锁确保了同一时间只有一个线程能访问该对象的成员变量。例如: ```java public class...

    并发编程之synchronized&Lock&AQS详解(1)1

    `synchronized`在JVM层面是基于监视器锁(Monitor)实现的,依赖于操作系统的Mutex lock(互斥锁),早期版本性能较低,但1.5以后通过一系列优化,如锁粗化、锁消除、轻量级锁、偏向锁和自旋锁等,性能得到了显著提升...

    Synchronized与Lock

    ReentrantLock支持公平锁和非公平锁的选择,公平锁保证按照等待时间顺序获取锁,而非公平锁则可能让等待时间短的线程优先获得锁。Lock还提供了一些synchronized不具备的功能,比如: 1. 可以尝试获取锁,即tryLock...

    关于synchronized、Lock的深入理解

    1. **使用方式**:`synchronized`是隐式同步,无需手动释放,而`Lock`是显式同步,需手动调用`lock()`和`unlock()`。 2. **控制能力**:`Lock`提供了更多控制选项,如可中断、可选择公平性、锁分离等。 3. **异常...

    [并发并行]_[初级]_[C++实现sychronized方式的对象锁]

    除了`std::lock_guard`,还可以使用`std::unique_lock`,它提供了更多的灵活性,比如可以手动解锁或者尝试不阻塞地获取锁。 C++还提供了一些其他的同步工具,如`std::condition_variable`(条件变量),它允许线程...

    Lock接口与synchronized关键字

    - **synchronized**支持可重入性,即同一个线程可以多次获取同一个对象的锁,而不会导致死锁。 - **Lock**接口也提供了可重入锁的实现。 2. **灵活性**: - **Lock**接口提供了更多的灵活性,例如: - 可以尝试...

    synchronized 的理解

    `wait()`方法使当前线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用`notify()`或`notifyAll()`方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。 ```java synchronized (lock) { // ...

    Synchronized关键字的用法

    - 这种情况下,通常的做法是将该状态变量声明为一个对象,并在需要同步的地方使用这个对象作为锁。 - 示例: ```java private final Object lock = new Object(); public void updateStatus() { ...

    Java线程之锁对象Lock-同步问题更完美的处理方式代码实例

    在使用Lock对象时,需要注意锁的获取和释放。Lock对象可以使用lock()方法来获取锁,并使用unlock()方法来释放锁。在finally块中释放锁可以确保锁最终被释放,即使发生异常情况。 Lock对象也可以用来实现读写锁...

    java 多线程synchronized互斥锁demo

    2. **同步代码块**:指定一个对象作为监视器,只有获取到该对象锁的线程才能执行代码块: ```java Object lock = new Object(); public void sharedMethod() { synchronized(lock) { // 代码块 } } ``` 在...

    Java synchronized关键字和Lock接口实现原理

    Java synchronized关键字和Lock接口实现原理 Java 中的 synchronized 关键字和 Lock 接口是两种常用的线程同步机制,它们都可以用来解决并发...但是,synchronized 关键字和 Lock 接口的实现原理和使用方法是不同的。

    Lock、Synchoronized和ReentrantLock的使用

    Synchronized 的优点是易于使用和理解,编译器通常会对其进行优化,可以提高性能。然而,Synchronized 也有一些缺点,如它不能被Interrupt,且在资源竞争激烈的情况下性能会下降。 二、ReentrantLock ...

    第15讲 synchronized和ReentrantLock有什么区别呢?1

    除了了解基本使用和案例外,深入理解它们的底层实现,如锁膨胀、降级,以及轻量级锁、重量级锁、自旋锁和偏斜锁等概念,对于成为一个合格的Java并发开发者至关重要。同时,掌握java.util.concurrent.locks包中的其他...

    深入Synchronized和java.util.concurrent.locks.Lock的区别详解

    使用Lock时,程序员需要显式地调用lock()来获取锁,并在finally块中确保调用unlock()来释放锁,这增加了代码的复杂性,但也带来了更高的控制度。Lock的优势在于它支持更细粒度的锁控制,可以提高并发性能,因为它...

    java 锁 Lock接口详解.docx

    4. **状态查询**:`synchronized`无法检查是否已获取锁,而`Lock`的`isHeldByCurrentThread()`和`isLocked()`方法可以查询锁的状态。 在使用`Lock`时,需要注意手动释放锁,避免死锁。`Lock`的`unlock()`方法必须在...

    Java synchronized详细解读.docx

    对于静态(`static`)方法,`synchronized`关键字锁定的是类的Class对象,因此,无论有多少个类的实例,所有线程在访问静态同步方法时都需要获取类的Class对象锁。这意味着,即使有多个类实例,所有线程也无法同时执行...

    ReentrantLock 与 synchronized 简介

    - **可中断等待**:通过`lock.tryLock()`和`lock.tryLock(long timeout, TimeUnit unit)`方法,可以在等待获取锁时响应中断。 - **锁共享**:`ReentrantLock`支持共享锁,允许多个线程同时获取锁,这对于读多写少...

    Java对象锁和类锁全面解析(多线程synchronize

    Java对象锁和类锁是Java多线程编程中至关重要的概念,它们是通过`synchronized`关键字来实现的,用于确保代码在并发环境下的线程安全。在这个全面解析中,我们将深入探讨这两个锁机制,理解它们的工作原理以及如何在...

Global site tag (gtag.js) - Google Analytics