Java Thread Synchroize两种方式的优劣

Context:

关于Thread老是看了忘,看了忘记。还是写下来吧。翻译的是orcale官网的锁解释文档地址

锁:

同步机制是围绕内部实体即intrinsic lock(intrinsic固有的、本质的)、monitor lock(监控锁)。Intrinsic lock在同步上扮演两个角色:1.强制的排他性读取对象的状态(也就是线程访问对象的属性、方法等是互斥的)、2保持happens-before relationship来确保变量、方法的可见性。

每个对象都有与其关联的intrinsic lock。按照惯例,一个线程需要 排他的、一致性(consistent)读取对象的属性,必须获取该对象的锁。并在处理完后释放intrinsic lock。在线程获取和释放锁之间,线程被称为拥有intrinsic lock。只要一个线程持有intrinsic lock,其他的线程尝试获取这个锁时就会被阻塞。

两种Synchronized:

Synchronized方法:

用法: public
synchronized void sayHello(){}

a)非静态方法:intrinsic lock是该调用方法的对象,如b.sayHello  线程持有的intrinsic lock就是对象b的intrinsic lock

b) 静态方法:例如 public static synchronized void getInstance()。调用是Test.getInstance();这里没有对象,线程持有的intrinsic lock是Test对象对应的Class类的对象,也就是假设Test类的对象testObject.getClass()所获得的对象。而该对象是在类的加载(Loading)阶段 在Java堆中生成一个代表改类的java.lang.Class对象,作为方法区的访问入口。(详见我以前的博客点击打开链接 
 )所以他是类级别的锁。

Synchronized声明:

用法:

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}

a)不是用该方法的对象来做为intrinsic lock,而是你指定任意一个对象

好处

1:不对整个方法进行同步,而是对一部分进行同步,效率要高些,也更安全(从同步的方法中调用别的对象的方法,可能造成Liveness问(如:死锁)。如例子,就没有吧nameList.add(name);加到里面。

:

public class MsLunch {
    private long c1 = 0;
    private long c2 = 0;
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void inc1() {
        synchronized(lock1) {
            c1++;
        }
    }

    public void inc2() {
        synchronized(lock2) {
            c2++;
        }
    }
}

2.c1的改变和c2的改变没什么逻辑上的关联,可以两个线程交叉改变。所以就没有必要用Synchronized Method,否则锁是该方法对象,两个inc1、inc2无法被两个线程同时访问。

重新进入Synchronized:

虽然a线程无法进入b线程锁住的方法,但是b线程可以再次进入b线程持有锁的方法,并对锁的进入进行累加。这样就可以递归调用了嘛。

时间: 2024-10-10 08:10:36

Java Thread Synchroize两种方式的优劣的相关文章

java笔记线程两种方式模拟电影院卖票

1 public class SellTicketDemo { 2 public static void main(String[] args) { 3 // 创建三个线程对象 4 SellTicket st1 = new SellTicket(); 5 SellTicket st2 = new SellTicket(); 6 SellTicket st3 = new SellTicket(); 7 8 // 给线程对象起名字 9 st1.setName("窗口1"); 10 st2.

一步步分析Java深拷贝的两种方式-clone和序列化

今天遇到一道面试题,询问深拷贝的两种方法.主要就是clone方法和序列化方法.今天就来分析一下这两种方式如何实现深拷贝.如果想跳过解析的朋友,直奔"重点来了!"寻找答案. clone方法 例1:我们不妨建立一个Exam对象 考试类Exam.java文件 public class Exam implements Cloneable { private int examId; private String examName; public Exam() { } public Exam(in

采用java和数据库两种方式进行加锁

java代码加锁 publicstatic synchronized int generate(StringtableName){Stringsql = "select value from t_table_id where table_name=?";Connectionconn = null;PreparedStatementpstmt = null;ResultSetrs = null;intvalue = 0;try{conn= DbUtil.getConnection();p

Java 和 数据库两种方式进行加锁

java方式: publicstatic synchronized int generate(StringtableName){ Stringsql = "select value from t_table_id where table_name=?"; Connectionconn = null; PreparedStatementpstmt = null; ResultSetrs = null; intvalue = 0; try{ conn= DbUtil.getConnecti

JAVA连接Oracle两种方式

以前学习.NET连接数据库时,也是做各种的连接配置.而如今在用到java操纵Oracle时,同样是一些的操作.在此总结一下. 1.JDBC_ODBC连接数据库 此方法需要配置ODBC数据源,本机必须有Oracle数据库 1.配置数据源 打开控制面板--管理工具--数据源 2.接下来在代码中连接即可 //使用jdbc_odbc桥接方式连接,需要配置数据源 public static void main(String [] args){ try{ //1.加载驱动 Class.forName("su

java及javascript两种方式获取YYYY-MM-dd HH:mm:ss格式的日期字符串

一.java方式 String leaveTime=""; SimpleDateFormat sDateFormat=new SimpleDateFormat("YYYY-MM-dd HH:mm:ss"); Date date=new Date(); leaveTime=sDateFormat.format(date); 二.javascript方式 <script type="text/javascript"> $().ready(

java生成Excel两种方式

方法一,利用第三方jar包:jxl.jar 无论方法一方法二最后最好用转换成流传给前端. 1 public void createExcel(){ 2 try{ 3 //打开文件 4 WritableWorkbook workbook = Workbook.createWorkbook(new File("test.xls")); 5 //生成名为"第一页"的工作表,参数0表示这是第一页 6 WritableSheet sheet = workbook.create

java 创建对象的两种方式

一: Object object = new Object(); 二: public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException { //可以通过映射的方式来获取 DemoTest2 myobject = (DemoTest2)Class.forName("DemoTest2").newInstance(); m

java基础知识回顾之java Thread类学习(三)--java线程实现常见的两种方式实现好处:

总结:实现Runnable接口比继承Thread类更有优势: 1.因为java只能单继承,实现Runnable接口可以避免单继承的局限性 2.继承Thread类,多个线程不能处理或者共享同一个资源,但是实现Runnable接口可以处理同一个资源. 下面我们做个测试:验证下.车站的售票系统售票的例子,车站的各个售票口相当于各个线程,我们先使用第一种方法几继承Thread类的方式实现: 代码如下: package com.lp.ecjtu.Thread; /** * * @author Admini