java中每个对象都有一个隐式的锁,如果一个方法由synchronized关键字声明,那些对象的锁将保护整个方法。
也就是说,要调用这个方法,线程必须先获得对象的锁。
隐式对象锁只有一个关联条件。wait方法把线程加到等待集中,notify/notifyAll方法解除等待线程的阻塞状态。
也两个方法等价于Condition(条件变量)的await,signal/signalAll方法。
隐式的锁和条件存在一些缺点。如下:
1.不能中断一个正在试图获得锁的线程。
2.试图获得锁时不能设定超时。
3.每个锁只有一个条件有时候显得不够用。
4.虚拟机的加锁原语不能很好地映射到硬件可用的最有效的加锁机制上。
在下面三个条件下,对一个域的并行访问是安全的:
1.域是volatile的。
2.域是final的,并且在构造器调用完成后被访问。
3.对域的访问有锁保护。
银行转账例子:(出自《JAVA2核心技术第7版卷2高级特性》书中例子)
/**
This program shows how multiple threads can safely access a data structure, using
synchronized methods.
*/
public class SynchBankTest2
{
public static void main(String[] args)
{
Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE);
int i;
for (i = 0; i < NACCOUNTS; i++)
{
TransferRunnable r = new TransferRunnable(b, i, INITIAL_BALANCE);
Thread t = new Thread(r);
t.start();
}
}
public static final int NACCOUNTS = 100;
public static final double INITIAL_BALANCE = 1000;
}
/**
A bank with a number of bank accounts.
*/
class Bank
{
/**
Constructs the bank.
@param n the number of accounts
@param initialBalance the initial balance
for each account
*/
public Bank(int n, double initialBalance)
{
accounts = new double[n];
for (int i = 0; i < accounts.length; i++)
accounts[i] = initialBalance;
}
/**
Transfers money from one account to another.
@param from the account to transfer from
@param to the account to transfer to
@param amount the amount to transfer
*/
public synchronized void transfer(int from, int to, double amount)
throws InterruptedException
{
while (accounts[from] < amount)
wait();
System.out.print(Thread.currentThread());
accounts[from] -= amount;
System.out.printf(" %10.2f from %d to %d", amount, from, to);
accounts[to] += amount;
System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
notifyAll();
}
/**
Gets the sum of all account balances.
@return the total balance
*/
public synchronized double getTotalBalance()
{
double sum = 0;
for (double a : accounts)
sum += a;
return sum;
}
/**
Gets the number of accounts in the bank.
@return the number of accounts
*/
public int size()
{
return accounts.length;
}
private final double[] accounts;
}
/**
A runnable that transfers money from an account to other
accounts in a bank.
*/
class TransferRunnable implements Runnable
{
/**
Constructs a transfer runnable.
@param b the bank between whose account money is transferred
@param from the account to transfer money from
@param max the maximum amount of money in each transfer
*/
public TransferRunnable(Bank b, int from, double max)
{
bank = b;
fromAccount = from;
maxAmount = max;
}
public void run()
{
try
{
while (true)
{
int toAccount = (int) (bank.size() * Math.random());
double amount = maxAmount * Math.random();
bank.transfer(fromAccount, toAccount, amount);
Thread.sleep((int) (DELAY * Math.random()));
}
}
catch (InterruptedException e) {}
}
private Bank bank;
private int fromAccount;
private double maxAmount;
private int repetitions;
private int DELAY = 10;
}
分享到:
相关推荐
java同步synchronized关键字用法示例
java多线程中synchronized关键字的用法 解压密码 www.jiangyea.com
Java 线程同步机制中 synchronized 关键字的理解 Java 的线程同步机制是为了解决多个线程共享同一片存储空间所带来的访问冲突问题。其中,synchronized 关键字是 Java 语言中解决这种冲突的重要机制。 ...
Java 中的 synchronized 关键字与线程平安问题 在 Java 中,synchronized 关键字是一个非常重要的概念,它用于解决线程同步问题。但是,很多开发者对 synchronized 关键字的理解并不够深入,本文将通过实例解析 ...
synchronized关键字在java中的重要性 以及常用的方法 还有它的详解
Java 并发编程 Synchronized 关键字实现原理 Synchronized 关键字是 Java 并发编程中最基本的同步机制,它可以保证线程安全,包括原子性、可见性和有序性。Synchronized 关键字可以修饰方法或代码块,使得在同一...
Synchronized关键字的用法
Lock接口与synchronized关键字在Java并发编程中都是用于实现同步机制的重要工具,但它们在使用方式、功能特性以及灵活性等方面存在一些显著的差异。 首先,从使用方式上来看,synchronized是Java语言内置的关键字,...
java基本教程之synchronized关键字java多线程教程共19页.pdf.zip
并发编程原理学习:synchronized关键字.doc
java synchronized关键字原理、自定义一把锁来实现同步等
Java多线程synchronized关键字详解(六)共5页.pdf.zip
线程安全,使用synchronized关键字
5-4JVM内置锁synchronized关键字详解.mp4
【ASP.NET编程知识】实例解析Java中的synchronized关键字与线程安全问题.docx
主要介绍了Java中synchronized关键字的用法,针对synchronized修饰方法的使用作出了简单讲解和演示,需要的朋友可以参考下
Java并发编程---synchronized关键
NULL 博文链接:https://seandsky-boyy-163-com.iteye.com/blog/1340783
开启了10个线程,每个线程都累加了10000000次,如果结果正确的话总数应该是10*10000000=1000000000.可是运行多次结果都不是这个数,而且每次运行结果都不一样。 线程安全问题主要来源于JMM的设计,主要集中在主内存...