多线程同步
举个银行取钱的例子来说
public class ThreadTest13 {
public static void main(String[] args) {
Account account=new Account("叫我男神O(∩_∩)O",5000);
Thread t1=new Thread(new Processor(account));
Thread t2=new Thread(new Processor(account));
t1.start();
t2.start();
}
}
//取款的线程
class Processor implements Runnable{
//账户
Account act;
Processor(Account act){
this.act=act;
}
public void run() {
act.withdraw(1000);
System.out.println(act.getActno()+"取款1000块成功,余额:"+act.getbalance());
}
}
//账户
class Account{
//属性
private String actno;
private double balance;
//构造方法
public Account() {}
public Account(String actno,double balance) {
this.setActno(actno);
this.setbalance(balance);
}
//set and get
public String getActno() {
return actno;
}
public void setActno(String actno) {
this.actno=actno;
}
public double getbalance() {
return balance;
}
public void setbalance(double balance) {
this.balance=balance;
}
//对外提供一个取款的方法
public synchronized void withdraw(double money) {
synchronized (this) {
//把要同步的代码放到同步语句块
/*
* 原理t1 和t2
* t1线程执行到此处,遇到的synchroized这个关键字,就回去找this对象锁
*如果找到了this对象锁,则进入同步语句块中执行程序,当同步语句块中代码执行结束,t1线程归还this对象锁。
*
* 在t1线程执行同步语句块过程中,如果t2线程也过来执行以下程序,也会遇到synchronzed关键字,所以也去找this对象锁,但是该对象锁被t1线程持有,只能在此处等待this对象锁的归还
*/
double after=balance-money;
//更新
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.setbalance(after);
}
}
}
关于synchronized(锁)的小方面
t1与t2共享一个资源时(同一个进程的线程是共享其进程的*内存和资源*
共享的内存是*堆内存和方法内存* 栈内存不共享,每个线程有自己的栈空间(一个线程一个栈))
public class ThreadTest14 {
public static void main(String[] args) throws InterruptedException {
// TODO 自动生成的方法存根
MyClass mc =new MyClass();
F a=new F(mc);//t1与t2共享一个mc
Thread t1=new Thread(a);
t1.setName("t1");
Thread t2=new Thread(a);
t2.setName("t2");
t1.start();
//保证t1先执行
Thread.sleep(1000);
t2.start();
}
}
class F implements Runnable{
MyClass mc;
F(MyClass mc){
this.mc=mc;
}
public void run() {
if (Thread.currentThread().getName().equals("t1"))
mc.m1();
if(Thread.currentThread().getName().equals("t2"))
mc.m2();
}
}
class MyClass{
public synchronized void m1() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("m1...");
}
// public void m2() { m2不需要等m1结束m2 没有synchronized关键字
// System.out.println("m2....");
// }
public synchronized void m2(){//m2方法会等m1结束 t1和t2共享一个mc ,并且m1和m2都有synchronized
System.out.println("m2......");
}
}
第一次m2没加synchronized关键字(没和m1公用一个茅坑)
第二次m2加了synchronized关键字(和m1共同享用一个茅坑)
对象锁(不止一个)
m2方法不会等m1方法结束 ,t1和t2不共享同一mc内存。
public class ThreadTest15 {
public static void main(String[] args) throws Exception {
MyClass01 mc1 = new MyClass01();
MyClass01 mc2 = new MyClass01();
B b1 = new B(mc1);
B b2 = new B(mc2);
//*t1与t2 不共享同一mc内存*
Thread t1 = new Thread(b1);
t1.setName("t1");
Thread t2 = new Thread(b2);
t2.setName("t2");
t1.start();
//保证t1先执行
Thread.sleep(1000);
t2.start();
}
}
class B implements Runnable{
MyClass01 mc;
B(MyClass01 mc){
this.mc = mc;
}
@Override
public void run() {
if (Thread.currentThread().getName().equals("t1")) {
mc.m1();
}
if (Thread.currentThread().getName().equals("t2")) {
mc.m2();
}
}
}
class MyClass01{
public synchronized void m1(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("m1....");
}
//m2方法不会等m1方法结束 ,t1和t2不共享一个mc
public synchronized void m2(){
System.out.println("m2......");
}
}
类锁(只有一个,synchronized+静态方法)
因为有synchronized添加到静态方法上面的,线程执行到此方法会找类锁m2方法等m1方法结束之后才能执行,虽然t1与t2的mc对象不一样,但是m2方法还是会等m1的
(就好像两个人,分别去两个不同的茅坑上厕所,但是只有你手里有一瓢水可以冲,他不确定他上的时候有没有水冲,所以得等你上完,再拿水上)
/*
* 类锁 类只有一个 所以是类级别的,只有一个
* */
public class ThreadTest16 {
public static void main(String[] args) throws Exception {
MyClass03 mc1 = new MyClass03();
MyClass03 mc2 = new MyClass03();
Thread t1 = new Thread(new D(mc1));
Thread t2 = new Thread(new D(mc2));
t1.setName("t1");
t2.setName("t2");
t1.start();
Thread.sleep(1000);
t2.start();
}
}
class D implements Runnable{
MyClass03 mc;
D(MyClass03 mc){
this.mc = mc;
}
public void run(){
if ("t1".equals(Thread.currentThread().getName())) {
mc.m1();//用的还是类锁 和对象没有关系
}
if("t2".equals(Thread.currentThread().getName())){
mc.m2();
}
}
}
class MyClass03{
//synchronized 添加到静态方法上面的,线程执行到此方法会找类锁
public synchronized static void m1(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("m1......");
}
//m2方法等m1方法结束之后才能执行,因为有synchronized
//线程执行该代码需要类锁 但是类锁只有一个
public synchronized static void m2(){
System.out.println("m2......");
}
}
Thread.setDaemon(true);
*守护线程
等其他用户线程全部结束后则守护线程退出