java 多线程 Synchronized方法和方法块 synchronized(this)和synchronized(object)的理解

synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。

1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:
public synchronized void accessVal(int newVal);
synchronized
方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized
方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得
该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized
的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变
量的方法均被声明为 synchronized)。
Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
synchronized
方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为
synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized
方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized
,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。

对synchronized(this)的一些理解(很细致,感谢作者!)

我对synchronized(this)和synchronized(object)的理解:

误区一:synchronized关键字只能用在实现Runnable或者继承了Thread类的子类的方法里面。


解:如果有一块代码(或方法)可能被多个线程同时访问,然后里面操作的数据修改操作可能因为不同线程的操作而不一致的时候,使用synchronized
锁定这块代码,确保同时只有一个线程访问这个代码块。也就是说,关键字synchronized可以用在任何类的方法里面,即使该类没有实现
Runnable接口或者继承Thread类。

误区二:synchronized(this)和synchronized(object)作用范围完全不同。

正解:当 多个线程 访问同一个类A 的 方法A()的时候
并且 这个方法A() 要求 一个线程执行完了之后 在给另外一个线程去执行

那么  这个方法A()   9必须加上  synchronized 关键字

或者  在 该方法A()中  写上 synchronized(this//指代当前类A的实例){}

如果不在声明方法A()时 加上synchronized关键字 或者 不在方法A()中加上synchronized(this){}
同步块的时候

可以在 线程类的RUN 方法内
synchronized(Object //指代类A的实例){
 Object.A();
}
实现多线程同时有序访问该同步块内类A的方法A()的目的

object本身就包含this的情况。

this指代的是当前同步块所在方法所在的类,当不需要引用别的类的时候。

object指代的是需要调用的类,引用了别的类,且需要处理多线程并发访问时,object指代的是被引用的类。如果没有引用别的类,则指代的就是同步块所在方法所在的类本身。

例:

public class 访问类 {

 public void A方法() {
  //synchronized (this) {
   for (int i = 0; i < 100; i++) {
    System.out.println(Thread.currentThread().getName() + " i = "
      + i);
   }
  //}
 }

 public void B方法() {
  //synchronized (this) {
   for (int i = 0; i < 100; i++) {
    System.out.println(Thread.currentThread().getName() + " i = "
      + i);
   }
  //}
 }
}
public class 实例线程类 {
 public static void main(String[] args) {
  访问类 Object = new 访问类();

  Thread t1 = new Thread(new 线程A(Object));
  Thread t2 = new Thread(new 线程B(Object));
  t1.start();
  t2.start();
 }
}

class 线程A implements Runnable {
 private 访问类 object;

 public 线程A(访问类 object) {
  // TODO Auto-generated constructor stub
  this.object = object;
 }

 @Override
 public void run() {
  // TODO Auto-generated method stub
  synchronized (object) {
   object.A方法();
  }
 }

}
class 线程B implements Runnable {
 private 访问类 object;

 public 线程B(访问类 object) {
  // TODO Auto-generated constructor stub
  this.object = object;
 }

 @Override
 public void run() {
  // TODO Auto-generated method stub
   synchronized (object) {
   object.B方法();
   }
 }

}
时间: 2024-11-08 20:12:56

java 多线程 Synchronized方法和方法块 synchronized(this)和synchronized(object)的理解的相关文章

java多线程并发(一)——Semaphore,volatile,synchronized ,Lock

在并发编程中,我们通常会遇到以下三个问题:原子性问题,可见性问题,有序性问题.我们先看具体看一下这三个概念: 1.原子性 原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行. 一个很经典的例子就是银行账户转账问题 2.可见性 可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值. 3.有序性 有序性:即程序执行的顺序按照代码的先后顺序执行. Semaphore 简介 信号量(Semaphore),有时被称为信号

【JAVA多线程中使用的方法】

一.sleep和wait的区别. 1.wait可以指定时间,也可以不指定. 而sleep必须制定. 2.在同步的时候,对于CPU的执行权和以及锁的处理不同. wait:释放执行权,释放锁. sleep:释放执行权,不释放锁. 二.线程是否安全? 1 class Test implements Runnable 2 { 3 public synchronized void show() 4 { 5 try 6 { 7 wait(); 8 } 9 catch (InterruptedExceptio

Java多线程_wait/notify/notifyAll方法

关于这三个方法,我们可以查询API得到下列解释: wait():导致当前的线程等待,直到其他线程调用此对象的notify( ) 方法或 notifyAll( ) 方法或者指定的事件用完 notify():唤醒在此对象监视器上等待的单个线程 notifyAll():唤醒在此对象监视器上等待的所有线程 我们需要注意的点(1)wait().notify/notifyAll() 方法是Object的本地final方法,无法被重写. (2)wait() 与 notify/notifyAll 方法必须在同步

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

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

Java多线程编程模式实战指南(二):Immutable Object模式--转载

本文由本人首次发布在infoq中文站上:http://www.infoq.com/cn/articles/java-multithreaded-programming-mode-immutable-object.转载请注明作者: 黄文海 出处:http://viscent.iteye.com. 多线程共享变量的情况下,为了保证数据一致性,往往需要对这些变量的访问进行加锁.而锁本身又会带来一些问题和开销.Immutable Object模式使得我们可以在不使用锁的情况下,既保证共享变量访问的线程安

Java多线程中的join方法

新建一个Thread,代码如下: 1 package com.thread.test; 2 3 public class MyThread extends Thread { 4 private String name; 5 public MyThread(String name) { 6 this.name = name; 7 } 8 @Override 9 public void run() { 10 for (int i = 0; i < 100; i++) { 11 System.out.

java多线程常见类与方法之java.util.concurrent.locks

1.java.util.concurrent.locks包里面的主要接口Lock,Condition,ReadWriteLock,主要的类为ReentrantLock,ReentrantReadWriteLock,ReentrantReadWriteLock.ReadLock,ReentrantReadWriteLock.WriteLock,LockSupport 2.ReentrantLock里面的主要方法为:lock(),unlock(),tryLock(),lockInterruptibl

java多线程四种实现方法

package com.zrun.TestThread; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Exec

java多线程 interrupt(), interrupted(), isInterrupted()方法区别

interrupt()方法: 作用是中断线程. 本线程中断自身是被允许的,且"中断标记"设置为true 其它线程调用本线程的interrupt()方法时,会通过checkAccess()检查权限.这有可能抛出SecurityException异常.  若线程在阻塞状态时,调用了它的interrupt()方法,那么它的"中断状态"会被清除并且会收到一个InterruptedException异常. 例如,线程通过wait()进入阻塞状态,此时通过interrupt()

Java 多线程, 同步访问, 线程锁,锁对象,ReentrantLock,synchronized

1.为什么要同步访问数据? 当两个或以上的线程需要共享对同一数据的存取,可能会发生共享数据的讹误. 2.实现同步的方式 2.1 ReentrantLock类 School类: class School{ private int stuNum; private Lock lock; private Condition condition; public School(int stuNum) { this.stuNum = stuNum; lock = new ReentrantLock(); co