好记性不如烂笔头~~

并发编程中synchronized关键字的地位很重要,很多人都称它为重量级锁。利用synchronized实现同步的基础:Java中每一个对象都可以作为锁。具体表现为以下三种形式。

(1)对于普通同步方法,锁是当前实例对象。

(2)对于静态同步方法,锁是当前类的Class对象。

(3)对于同步方法块,锁是synchronized括号里配置的对象。

一、普通同步方法

使用synchronized关键字修饰一个普通方法,锁住的是当前实例的对象。当synchronized锁住该对象后,别的线程如果也想拿到这个对象的锁,就必须等待这个线程执行完成释放锁,才能再次给对象加锁,这样才达到线程同步的目的。

实验一

class Synch{
public synchronized void test1(){
System.out.println("test1开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test1结束");
}
public synchronized void test2(){
System.out.println("test2开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test2结束");
}
} public class SyncTest extends Synch{ public static void main(String args[]){
Synch s=new Synch();
Thread t1=new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
s.test1();
} });
Thread t2=new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
s.test2();
}});
t1.start();
t2.start();
}
}

  实验结果:

分析上述代码,类Synch中有两个普通同步方法test1和test2.在主函数中实现了该类,同时定义两个thread线程,run方法中分别调用类Synch的方法。synchronized实现的普通同步方法,锁住的是当前实例对象,即Synch类对象。由于两个线程是调用的同一个对象中的同步方法,所以只有一个线程释放该对象的锁,另一个线程才能调用。

实验二

class Sync{
public synchronized void test(String threadname){ System.out.println(threadname+"开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(threadname+"结束"); }
}
class MyThread extends Thread{
public int i;
public MyThread(int i){
this.i=i;
}
Sync s=new Sync();
public void run(){
//Sync sync=new Sync();
s.test("Thread"+i);
}
}
public class SynTest {
public static void main(String args[]){
for(int i=0;i<3;i++){
Thread thread=new MyThread(i);
thread.start();
}
}
}

 实验结果:

上述代码,每个线程中都new了一个Sync类的对象,也就是产生了三个Sync对象,由于不是同一个对象,所以可以多线程同时运行synchronized方法。

二、静态同步方法

对于静态同步方法,锁是当前类的Class对象,所以,static synchronized方法也相当于全局锁,相当于锁住了代码段。只有一个线程结束后,另一个线程才能获得锁。

实验三

class Synch{
public static synchronized void test1(){
System.out.println("test1开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test1结束");
}
public static synchronized void test2(){
System.out.println("test2开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("test2结束");
}
} public class SyncTest extends Synch{ public static void main(String args[]){
Synch s1=new Synch();
Synch s2=new Synch();
Thread t1=new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
s1.test1();
} });
Thread t2=new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
s2.test2();
}});
t1.start();
t2.start();
}
}

  实验结果:

三、同步方法块

这部分更好理解,锁住的是synchronized括号里配置的对象。

实验四

public class Threadtest implements Runnable{

	@Override
public void run() {
// TODO Auto-generated method stub
synchronized(this){
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
}
}
}
public static void main(String[] args) {
Threadtest t1 = new Threadtest();
Thread ta = new Thread(t1, "A");
Thread tb = new Thread(t1, "B");
ta.start();
tb.start();
}
}

运行结果:

上述代码,synchronized代码块括号里配置的对象是this,同一个对象,所以只有一个线程访问该代码块结束后,释放锁,另一个线程才能访问该代码块。

需要注意的是,其他线程可以访问非synchronized(this)同步代码。如下代码

实验五

class MyThread1{
public void test1(){
synchronized(this){
System.out.println("同步代码块-test1开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("同步代码块-test1结束");
}
}
public void test2(){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("非同步代码块-test2");
}
}
public class ThreadTest1 {
public static void main(String args[]){
MyThread1 t=new MyThread1();
Thread t1=new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
t.test1();
} });
Thread t2=new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
t.test2(); } });
t1.start();
t2.start();
}
}

  运行结果:

synchronized括号里配置的是this,只是对这一段代码进行了加锁,同一个对象,只有一个线程能访问该代码块,释放锁之后,其他线程才可以访问,但是并不影响其他线程访问非同步代码块。

同步代码块,同步方法的实现~~简单理解

对于同步代码块是使用monitorenter、monitorexit指令实现的。每个对象都有一个监视器锁(monitor),当monitor被占用时,就会处于锁定状态。

线程执行monitorenter指令尝试获取monitor的所有权。

  • 如果monitor的进入数为0,则该线程进入monitor,并将进入数设置为1
  • 如果该线程已经占有了该monitor,重新进入,进入数也要+1
  • 如果其他线程占用了monitor,则该线程进入阻塞状态,知道进入数为0

对于同步方法,常量池中多了ACC_SYNCHRONIZED标识符,方法调用时,先检查该标识符的访问标志,如果设置了,则进程先获取monitor,获取成功后才能执行方法体,方法执行完之后再释放monitor。

整理下,要不会忘记~~参考http://www.cnblogs.com/QQParadise/articles/5059824.html

Java中synchronized关键字理解的更多相关文章

  1. java中synchronized关键字分析

    今天我们来分析一下java中synchronized关键字.首先来看一段java代码:(本地编译环境为mac,jdk1.8的环境) Demo.java package com.example.spri ...

  2. java中synchronized关键字的用法

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  3. Java关键字-----------------java中synchronized关键字的用法

    在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. j ...

  4. Java中synchronized关键字你知道多少

    1.什么是synchronized 我们将其理解为同步锁,可以实现共享资源的同步访问,解决线程并发的安全问题.synchronize翻译成中文:同步,使同步.synchronized:已同步. 1.1 ...

  5. java中synchronized关键字基础-1

    1.synchronized关键字简介 synchronized是java中的一个关键字,在中文中为同步,也被称之为'同步锁',以此来达到多线程并发访问时候的并发安全问题,可以用来修饰代码块.非静态方 ...

  6. 从分布式锁角度理解Java的synchronized关键字

    分布式锁 分布式锁就以zookeeper为例,zookeeper是一个分布式系统的协调器,我们将其理解为一个文件系统,可以在zookeeper服务器中创建或删除文件夹或文件.设D为一个数据系统,不具备 ...

  7. 浅谈对java中锁的理解

    在并发编程中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,在java中synchronized关键字被常用于维护数据一致性.synchronized机制是给共享 ...

  8. java中锁的理解

    在并发编程中,经常遇到多个线程访问同一个 共享资源 ,这时候作为开发者必须考虑如何维护数据一致性,在java中synchronized关键字被常用于维护数据一致性.synchronized机制是给共享 ...

  9. Java的synchronized关键字:同步机制总结

    JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程 ...

随机推荐

  1. 第 1 篇 Scrum 冲刺博客(5.21)

    一.Alpha阶段认领的任务 二.明日任务安排 成员 5.22任务安排 工时 陈芝敏 调用小程序接口获取用户微信登录权限,初始化 1h 在页面显示倒计时 5h 冯晓凤 继续学习微信开放文档 5h 江晓 ...

  2. Typora--我用过的最好用的markdown编辑器

    Typora Markdown编辑器,让人专注于书写的编辑器,书写博客和笔记的不二之选! 之前使用过程中只是使用了默认的功能,没有进行任何的第三发查件使用,各种方面出现了很多的局限性,比如插入了图片之 ...

  3. 7. Jackson用树模型处理JSON是必备技能,不信你看

    每棵大树,都曾只是一粒种子.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众号[BA ...

  4. 新手学习java路线

    关于新手学习java的路线 笔者也是根据这个路线学习的,希望对你们有所帮助. 首先你要确定你是学习java 并且能够踏踏实实的走下去.一定要多学习,我也可以一直陪你走下去的. 笔者一年工作经验,科班毕 ...

  5. 为什么网站URL需要设置为静态化

    http://www.wocaoseo.com/thread-95-1-1.html       为什么网站URL需要静态化?网站url静态化的好处是什么?现在很多网站的链接都是静态规的链接,但是网站 ...

  6. python - 平方根格式化 + 字符串分段组合

    题目来源:python123 平方根格式化 描述 获得用户输入的一个整数a,计算a的平方根,保留小数点后3位,并打印输出.‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪ ...

  7. day42:HTML标签和CSS选择器

    目录 1.HTML 1.1 文档结构 1.2 head标签 1.3 body标签 1.3.1 h1-h6标签 1.3.2.br标签:换行 1.3.3.hr标签:一行横线 1.3.4 a标签:超链接标签 ...

  8. Android开发之recycleView详解代码,看完包你熟练掌握recycleView的用法。转自网络经典文章

    来源 http://jinyudong.com/2014/11/13/Introduce-RecyclerView-%E4%B8%80/ 编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在 ...

  9. Python pymsql模块

    pymsql pymysql这款第三方库可以帮助我们利用python语言与mysql进行链接 基本使用 首先要下载pymysql pip install pymsql 以下是pymysql的基本使用 ...

  10. Google Kick Start 2020 Round B T4 Wandering Robot

    题意 一个\(n \times m\)的矩形空间,起点是\((1,1)\),终点是\((n,m)\). 假设当前位于\((x,y)\): 如果当前位于最后一行,那么下一步只能走向\((x,y+1)\) ...