线程同步(一)

上篇文章讲述了什么是线程,以及在Linux系统下线程的相关操作

 线程(Linux系统实现)_小梁今天敲代码了吗的博客-CSDN博客

本文将继续讲述线程的相关知识——线程同步

目录

1.线程同步的概念

2.线程不同步可能会发生什么

3.线程同步方式   

4.互斥锁

申请一个互斥锁

尝试获取互斥锁

互斥锁解锁

互斥锁示例

1.线程同步的概念

        线程同步是指在多线程编程中,为了保证多个线程按照某种特定的方式正确、有序地执行,需要进行线程间的协作与同步。在多线程编程中,当多个线程共享同一份资源时,由于线程的执行顺序是不确定的,因此会存在一些并发问题,如死锁、竞态条件、资源争用等问题。为了避免这些问题,需要对线程进行同步。线程同步实际上就是通过线程之间的协作,使得线程能够按照一定的顺序来访问共享资源,从而避免并发问题的发生。常用的线程同步机制有互斥锁、信号量、条件变量等。

2.线程不同步可能会发生什么

线程不同步可能会导致以下问题:

1. 竞态条件(Race Condition):多个线程同时访问、修改一份共享资源,可能会导致资源的状态不确定,进而导致程序出现逻辑错误,甚至崩溃。

2. 死锁(Deadlock):多个线程在等待对方释放锁,导致所有线程都无法继续执行,程序陷入死循环,最终可能会崩溃。

3. 饥饿(Starvation):某些线程可能因为无法获取资源而一直等待,导致无法正常执行,进而影响整个程序的性能。

4. 资源争用(Resource Contention):多个线程同时竞争同一份资源,导致资源的使用效率下降,总体性能降低。

示例:两个线程交替数数(每个线程数 50 个数,交替数到 100)

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>#define MAX 50
// 全局变量
int number;// 线程处理函数
void* funcA_num(void* arg)
{for(int i=0; i<MAX; ++i){int cur = number;cur++;usleep(10);number = cur;printf("Thread A, id = %lu, number = %d\n", pthread_self(), number);}return NULL;
}void* funcB_num(void* arg)
{for(int i=0; i<MAX; ++i){int cur = number;cur++;number = cur;printf("Thread B, id = %lu, number = %d\n", pthread_self(), number);usleep(5);}return NULL;
}int main(int argc, const char* argv[])
{pthread_t p1, p2;// 创建两个子线程pthread_create(&p1, NULL, funcA_num, NULL);pthread_create(&p2, NULL, funcB_num, NULL);// 阻塞,资源回收pthread_join(p1, NULL);pthread_join(p2, NULL);return 0;
}

在linux系统中编译,运行结果:

[itliang@localhost ~]$ ./xctb
Thread B, id = 140388304152320, number = 1
Thread A, id = 140388312545024, number = 1
Thread B, id = 140388304152320, number = 2
Thread A, id = 140388312545024, number = 2
Thread B, id = 140388304152320, number = 3
Thread A, id = 140388312545024, number = 3
Thread B, id = 140388304152320, number = 4
Thread A, id = 140388312545024, number = 4
Thread B, id = 140388304152320, number = 5
Thread A, id = 140388312545024, number = 5
Thread B, id = 140388304152320, number = 6
Thread B, id = 140388304152320, number = 7
Thread A, id = 140388312545024, number = 6
Thread B, id = 140388304152320, number = 7
Thread A, id = 140388312545024, number = 7
Thread A, id = 140388312545024, number = 8
Thread B, id = 140388304152320, number = 9
Thread B, id = 140388304152320, number = 10
Thread A, id = 140388312545024, number = 9
Thread A, id = 140388312545024, number = 10
Thread B, id = 140388304152320, number = 11
Thread B, id = 140388304152320, number = 12
Thread A, id = 140388312545024, number = 11
Thread A, id = 140388312545024, number = 12
Thread B, id = 140388304152320, number = 13
Thread A, id = 140388312545024, number = 13
Thread B, id = 140388304152320, number = 14
Thread B, id = 140388304152320, number = 15
Thread A, id = 140388312545024, number = 14
Thread B, id = 140388304152320, number = 15
Thread A, id = 140388312545024, number = 15
Thread A, id = 140388312545024, number = 16
Thread B, id = 140388304152320, number = 17
Thread B, id = 140388304152320, number = 18
Thread A, id = 140388312545024, number = 17
Thread A, id = 140388312545024, number = 18
Thread B, id = 140388304152320, number = 19
Thread A, id = 140388312545024, number = 19
Thread B, id = 140388304152320, number = 20
Thread B, id = 140388304152320, number = 21
Thread A, id = 140388312545024, number = 20
Thread A, id = 140388312545024, number = 21
Thread B, id = 140388304152320, number = 22
Thread B, id = 140388304152320, number = 23
Thread A, id = 140388312545024, number = 22
Thread A, id = 140388312545024, number = 23
Thread B, id = 140388304152320, number = 24
Thread B, id = 140388304152320, number = 25
Thread A, id = 140388312545024, number = 24
Thread B, id = 140388304152320, number = 25
Thread A, id = 140388312545024, number = 25
Thread A, id = 140388312545024, number = 26
Thread B, id = 140388304152320, number = 27
Thread B, id = 140388304152320, number = 28
Thread A, id = 140388312545024, number = 27
Thread A, id = 140388312545024, number = 28
Thread B, id = 140388304152320, number = 29
Thread A, id = 140388312545024, number = 29
Thread B, id = 140388304152320, number = 30
Thread B, id = 140388304152320, number = 31
Thread A, id = 140388312545024, number = 30
Thread A, id = 140388312545024, number = 31
Thread B, id = 140388304152320, number = 32
Thread B, id = 140388304152320, number = 33
Thread A, id = 140388312545024, number = 32
Thread A, id = 140388312545024, number = 33
Thread B, id = 140388304152320, number = 34
Thread B, id = 140388304152320, number = 35
Thread A, id = 140388312545024, number = 34
Thread A, id = 140388312545024, number = 35
Thread B, id = 140388304152320, number = 36
Thread B, id = 140388304152320, number = 37
Thread A, id = 140388312545024, number = 36
Thread A, id = 140388312545024, number = 37
Thread B, id = 140388304152320, number = 38
Thread B, id = 140388304152320, number = 39
Thread A, id = 140388312545024, number = 38
Thread A, id = 140388312545024, number = 39
Thread B, id = 140388304152320, number = 40
Thread B, id = 140388304152320, number = 41
Thread A, id = 140388312545024, number = 40
Thread A, id = 140388312545024, number = 41
Thread B, id = 140388304152320, number = 42
Thread B, id = 140388304152320, number = 43
Thread A, id = 140388312545024, number = 42
Thread A, id = 140388312545024, number = 43
Thread B, id = 140388304152320, number = 44
Thread B, id = 140388304152320, number = 45
Thread A, id = 140388312545024, number = 44
Thread A, id = 140388312545024, number = 45
Thread B, id = 140388304152320, number = 46
Thread B, id = 140388304152320, number = 47
Thread A, id = 140388312545024, number = 46
Thread A, id = 140388312545024, number = 47
Thread B, id = 140388304152320, number = 48
Thread A, id = 140388312545024, number = 48
Thread B, id = 140388304152320, number = 49
Thread B, id = 140388304152320, number = 50
Thread A, id = 140388312545024, number = 49
Thread A, id = 140388312545024, number = 50

        通过对上面例子的测试,可以看出虽然每个线程内部循环了 50 次每次数一个数,但是最终没有数到 100,通过输出的结果可以看到,有些数字被重复数了多次,其原因就是没有对线程进行同步处理,造成了数据的混乱。

3.线程同步方式   

线程同步方式有以下几种:

1. 互斥锁(Mutex):使用互斥锁来控制多个线程对共享资源的访问。只有获得锁的线程才能进入临界区进行操作,其他线程必须等待锁释放后才能进入。

2. 读写锁(Read-Write Lock):允许多个线程同时读取共享资源,但只允许一个线程写入共享资源。读写锁可以提高程序的并发性能,减少资源争用问题。

3. 条件变量(Condition Variable):用于等待特定条件的发生。当某个线程等待某个条件变量时,它会被阻塞,直到其他线程发出信号,通知条件变量已经满足。

4. 信号量(Semaphore):使用信号量来控制多个线程对有限数量资源的访问。信号量表示资源的数量,每个线程在使用完资源后必须释放信号量,以便其他线程可以使用资源。

以上是常见的几种线程同步方式,每种方式都有其适用的场景和优缺点,根据具体的应用场景选择适合的同步方式是非常重要的,这里先介绍互斥锁。

4.互斥锁

        互斥锁是线程同步最常用的一种方式,通过互斥锁可以锁定一个代码块,被锁定的这个代码块,所有的线程只能顺序执行 (不能并行处理),这样多线程访问共享资源数据混乱的问题就可以被解决了,需要付出的代价就是执行效率的降低,因为默认临界区多个线程是可以并行处理的,现在只能串行处理。

在 Linux 中互斥锁的类型为 pthread_mutex_t,创建一个这种类型的变量就得到了一把互斥锁:

pthread_mutex_t  mutex;

       在创建的锁对象中保存了当前这把锁的状态信息:锁定还是打开,如果是锁定状态还记录了给这把锁加锁的线程信息(线程 ID)。一个互斥锁变量只能被一个线程锁定,被锁定之后其他线程再对互斥锁变量加锁就会被阻塞,直到这把互斥锁被解锁,被阻塞的线程才能被解除阻塞。一般情况下,每一个共享资源对应一个把互斥锁,锁的个数和线程的个数无关。

Linux 提供的互斥锁操作函数如下,如果函数调用成功会返回 0,调用失败会返回相应的错误号:

// 初始化互斥锁
// restrict: 是一个关键字, 用来修饰指针, 只有这个关键字修饰的指针可以访问指向的内存地址, 其他指针是不行的
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
// 释放互斥锁资源            
int pthread_mutex_destroy(pthread_mutex_t *mutex);//mutex: 互斥锁变量的地址
//attr: 互斥锁的属性,一般使用默认属性即可,这个参数指定为 NULL

申请一个互斥锁

修改互斥锁的状态, 将其设定为锁定状态, 这个状态被写入到参数 mutex 中

int pthread_mutex_lock(pthread_mutex_t *mutex);

这个函数被调用,首先会判断参数 mutex 互斥锁中的状态是不是锁定状态:

        没有被锁定,是打开的,这个线程可以加锁成功,这个这个锁中会记录是哪个线程加锁成功
如果被锁定了,其他线程加锁就失败了,这些线程都会阻塞在这把锁上
当这把锁被解开之后,这些阻塞在锁上的线程就解除阻塞了,并且这些线程是通过竞争的方式对这把锁加锁,没抢到锁的线程继续阻塞

尝试获取互斥锁

        下面这个函数是尝试获取一个互斥锁。如果当前的锁没有被其他线程占用,则该函数会立即返回,线程成功获取锁,并返回0。否则,该函数会立即返回,线程不会阻塞,直接返回EBUSY错误码。

// 尝试加锁
int pthread_mutex_trylock(pthread_mutex_t *mutex);

        使用pthread_mutex_trylock函数获取锁的好处是,在获取锁的过程中不会引起线程阻塞,避免了由于长时间阻塞而导致的程序性能下降或死锁问题。但是,需要注意的是,在使用pthread_mutex_trylock函数时,如果获取锁失败,则需要有相应的处理措施来处理获取锁失败的情况。

互斥锁解锁

        通过调用pthread_mutex_unlock()函数将占用的互斥锁释放,以便其他线程可以竞争和访问共享资源。如果未正确解锁互斥锁,则可能会导致死锁或其他线程无法访问共享资源。因此,正确使用互斥锁是确保多线程代码正确运行的关键之一。

// 对互斥锁解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);

        我们可以将上面多线程交替数数的例子修改一下,使用互斥锁进行线程同步。两个线程一共操作了同一个全局变量,因此需要添加一互斥锁,来控制这两个线程。

互斥锁示例:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>#define MAX 100
// 全局变量
int number;// 创建一把互斥锁
// 全局变量, 多个线程共享
pthread_mutex_t mutex;// 线程处理函数
void* funcA_num(void* arg)
{for(int i=0; i<MAX; ++i){// 如果线程A加锁成功, 不阻塞// 如果B加锁成功, 线程A阻塞pthread_mutex_lock(&mutex);int cur = number;cur++;usleep(10);number = cur;pthread_mutex_unlock(&mutex);printf("Thread A, id = %lu, number = %d\n", pthread_self(), number);}return NULL;
}void* funcB_num(void* arg)
{for(int i=0; i<MAX; ++i){// a加锁成功, b线程访问这把锁的时候是锁定的// 线程B先阻塞, a线程解锁之后阻塞解除// 线程B加锁成功了pthread_mutex_lock(&mutex);int cur = number;cur++;number = cur;pthread_mutex_unlock(&mutex);printf("Thread B, id = %lu, number = %d\n", pthread_self(), number);usleep(5);}return NULL;
}int main(int argc, const char* argv[])
{pthread_t p1, p2;// 初始化互斥锁pthread_mutex_init(&mutex, NULL);// 创建两个子线程pthread_create(&p1, NULL, funcA_num, NULL);pthread_create(&p2, NULL, funcB_num, NULL);// 阻塞,资源回收pthread_join(p1, NULL);pthread_join(p2, NULL);// 销毁互斥锁// 线程销毁之后, 再去释放互斥锁pthread_mutex_destroy(&mutex);return 0;
}

linux系统运行结果:

[itliang@localhost ~]$ ./xctb
Thread A, id = 139912715360000, number = 1
Thread A, id = 139912715360000, number = 2
Thread A, id = 139912715360000, number = 3
Thread A, id = 139912715360000, number = 4
Thread A, id = 139912715360000, number = 5
Thread A, id = 139912715360000, number = 6
Thread A, id = 139912715360000, number = 7
Thread A, id = 139912715360000, number = 8
Thread A, id = 139912715360000, number = 9
Thread A, id = 139912715360000, number = 10
Thread A, id = 139912715360000, number = 11
Thread A, id = 139912715360000, number = 12
Thread A, id = 139912715360000, number = 13
Thread A, id = 139912715360000, number = 14
Thread A, id = 139912715360000, number = 15
Thread A, id = 139912715360000, number = 16
Thread A, id = 139912715360000, number = 17
Thread A, id = 139912715360000, number = 18
Thread A, id = 139912715360000, number = 19
Thread A, id = 139912715360000, number = 20
Thread A, id = 139912715360000, number = 21
Thread A, id = 139912715360000, number = 22
Thread A, id = 139912715360000, number = 23
Thread A, id = 139912715360000, number = 24
Thread A, id = 139912715360000, number = 25
Thread A, id = 139912715360000, number = 26
Thread A, id = 139912715360000, number = 27
Thread A, id = 139912715360000, number = 28
Thread A, id = 139912715360000, number = 29
Thread A, id = 139912715360000, number = 30
Thread A, id = 139912715360000, number = 31
Thread A, id = 139912715360000, number = 32
Thread A, id = 139912715360000, number = 33
Thread A, id = 139912715360000, number = 34
Thread A, id = 139912715360000, number = 35
Thread A, id = 139912715360000, number = 36
Thread A, id = 139912715360000, number = 37
Thread A, id = 139912715360000, number = 38
Thread A, id = 139912715360000, number = 39
Thread A, id = 139912715360000, number = 40
Thread A, id = 139912715360000, number = 41
Thread A, id = 139912715360000, number = 42
Thread A, id = 139912715360000, number = 43
Thread A, id = 139912715360000, number = 44
Thread A, id = 139912715360000, number = 45
Thread A, id = 139912715360000, number = 46
Thread A, id = 139912715360000, number = 47
Thread A, id = 139912715360000, number = 48
Thread A, id = 139912715360000, number = 49
Thread A, id = 139912715360000, number = 50
Thread B, id = 139912706967296, number = 51
Thread B, id = 139912706967296, number = 52
Thread B, id = 139912706967296, number = 53
Thread B, id = 139912706967296, number = 54
Thread B, id = 139912706967296, number = 55
Thread B, id = 139912706967296, number = 56
Thread B, id = 139912706967296, number = 57
Thread B, id = 139912706967296, number = 58
Thread B, id = 139912706967296, number = 59
Thread B, id = 139912706967296, number = 60
Thread B, id = 139912706967296, number = 61
Thread B, id = 139912706967296, number = 62
Thread B, id = 139912706967296, number = 63
Thread B, id = 139912706967296, number = 64
Thread B, id = 139912706967296, number = 65
Thread B, id = 139912706967296, number = 66
Thread B, id = 139912706967296, number = 67
Thread B, id = 139912706967296, number = 68
Thread B, id = 139912706967296, number = 69
Thread B, id = 139912706967296, number = 70
Thread B, id = 139912706967296, number = 71
Thread B, id = 139912706967296, number = 72
Thread B, id = 139912706967296, number = 73
Thread B, id = 139912706967296, number = 74
Thread B, id = 139912706967296, number = 75
Thread B, id = 139912706967296, number = 76
Thread B, id = 139912706967296, number = 77
Thread B, id = 139912706967296, number = 78
Thread B, id = 139912706967296, number = 79
Thread B, id = 139912706967296, number = 80
Thread B, id = 139912706967296, number = 81
Thread B, id = 139912706967296, number = 82
Thread B, id = 139912706967296, number = 83
Thread B, id = 139912706967296, number = 84
Thread B, id = 139912706967296, number = 85
Thread B, id = 139912706967296, number = 86
Thread B, id = 139912706967296, number = 87
Thread B, id = 139912706967296, number = 88
Thread B, id = 139912706967296, number = 89
Thread B, id = 139912706967296, number = 90
Thread B, id = 139912706967296, number = 91
Thread B, id = 139912706967296, number = 92
Thread B, id = 139912706967296, number = 93
Thread B, id = 139912706967296, number = 94
Thread B, id = 139912706967296, number = 95
Thread B, id = 139912706967296, number = 96
Thread B, id = 139912706967296, number = 97
Thread B, id = 139912706967296, number = 98
Thread B, id = 139912706967296, number = 99
Thread B, id = 139912706967296, number = 100

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/354044.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

816墨盒计算机无法与,西通PG-815、CL-816兼容墨盒和总结

推荐产品&#xff1a;西通PG-815、CL-816兼容墨盒 参考售价&#xff1a;黑色65元/个&#xff0c;彩色80元/个 产品特点&#xff1a;彩色打印也出色 产品特色&#xff1a;佳能原装墨盒贵是众所周知的&#xff0c;特别是中低端喷墨打印机的墨盒更贵&#xff0c;而且价格贵的同时容…

HP C6602A墨盒驱动

背景 现有一型号为HP C6602A的墨盒&#xff0c;需要研究其驱动方式&#xff0c;并使用合适的微控制器对其进行控制。 工作内容 一、 研究墨盒的驱动 墨盒的驱动原理和方法参考了现有开源项目InkShield的理论部分。由于HP C6602A是一款商业墨盒&#xff0c;HP公司并不提供技…

android 调用支付宝充值,提示系统繁忙,4000

今天在做支付宝充值的时候&#xff0c;遇到一个问题&#xff0c;如下图&#xff1a; 找了老半天的错误&#xff0c;没有找到错误在哪里了&#xff0c;上网半天也没有找到与之相关的错误&#xff0c;最后还是请教了一个大神&#xff0c;才知道错误的原因&#xff0c;代码&#x…

支付宝充值话费

充值流程&#xff1a; 进入充值页面---->输入手机号---->输入/选择充值金额----->进入支付方式页----->选择支付方式------>密码输入 ------>push/短信消息&#xff0c;充值成功

【经验教程】支付宝怎么充值手机话费?

支付宝怎么充值手机话费&#xff1f; 1、打开手机支付宝&#xff0c;并选择支付宝充值中心&#xff1b; 2、打开支付宝充值中心后&#xff0c;默认读取支付宝绑定的手机号码或修改成指定的手机号码充值&#xff1b; 3、选择要充值的金额&#xff0c;并完成支付&#xff1b; 4、…

springboot接入支付宝支付

在springboot项目中接入支付宝支付 一、在官网申请开通二、编写代码 一、在官网申请开通 进入支付宝开放平台 支付宝扫码登录注册&#xff0c;填写相关信息。 因为我们是开发者&#xff0c;所以支付宝给我们提供一个完整的沙箱环境&#xff0c;只要登录开放平台就会给我们提供…

golang对接支付宝支付

本文采用沙箱环境 1. 开启沙箱 文档&#xff1a;https://docs.open.alipay.com/200/105311/ 沙箱地址&#xff1a;https://openhome.alipay.com/platform/appDaily.htm 2. 生成应用公钥和秘钥&#xff08;已弃用&#xff09; 本文中的签名方法默认为 RSA2&#xff0c;采用支…

Flutter支付宝支付

_。插件选型&#xff1a; 1.tobias 2.flutter_alipay 3.alipay_kit 4.sy_flutter_alipay 因为flutter项目的flutter sdk是2.53 有空安全&#xff0c;所以排除掉三年没更新的sy_flutter_alipay&#xff0c; flutter_alipay排除掉的原因是本项目的dart sdk版本太低不支持…

如何测试支付宝手机充值的这个功能,写出测试用例

有人在面试软件测试的时候&#xff0c;被问到如何测试支付宝手机充值的这个功能&#xff0c;写出测试用例。 其实无论测试什么&#xff0c;我们首先的需要梳理软件业务的流程&#xff0c;来看看支付宝充值都有哪些流程&#xff1f; 首先&#xff0c;面试官如果给出的是这样一…

p2p银行充值功能模块 支付宝调用

银行充值简介 用户要想要投标的话&#xff0c;那么需要往p2p平台上进行充值 使用支付宝沙箱 调用支付宝充值接口进行测试 用户余额页面展示用户的余额 点击充值调用跳转到银行充值页面 输入密码&#xff0c;密码正确调转到支付宝支付平台 登录账号密码进行充值 充值成功记录到…

抓包抖音充值接口,实现微信支付宝充值抖币收款通道

前段时间搞了个抖音充值的通道&#xff0c;现在搞个YY充值的。 接下来这段时间的安排就是把各个这种平台的充值接口全分析一遍做成接口。 相比抖音的充值抖币接口&#xff0c;yy充值y币的风控就小很多&#xff0c;可以忽略不计&#xff0c;所以开发上也顺利很多。 把调用的相…

SpringBoot源码分析:SpringBoot整合Tomcat(三)

一、概述 SpringBoot整合Tomcat整体启动流程如下图&#xff0c;接下来我们就按照改流程分析SpringBoot中内嵌Tomcat的启动流程。 二、启动流程 通过AbstractApplicationContext.refresh方法进入AbstractApplicationContext.onRefresh方法。 之后进入子类ServletWebServerAppl…

Django对接支付宝实现支付宝充值金币功能

很多网站里都有金币、积分之类的虚拟货币&#xff0c;获取这些往往需要充值。那么问题来了&#xff0c;如何在Django中对接支付宝实现支付宝充值金币的功能呢&#xff1f;网上很多资料都是电商的&#xff0c;那些都会带有订单系统之类比较复杂&#xff0c;而充值金币功能不需要…

抓包抖音充值页面实现微信支付宝充值抖币,可提供api

抖币充值系统重写升级: 1.支持配置扫码配置多个CK 2.支持生成 微信/支付宝 支付二维码 扫码充值 3.支持 微信/支付宝 APP 直接唤醒充值 体验如下: 需要的小伙伴可私信 留言&#xff01; 整个开发流程思路是以下几步&#xff1a; 1.抓包分析抖音的充值的整个流程&#xff0…

如何使用支付宝充值美区App store的礼品卡

如何使用支付宝充值礼品卡 可能很多人不知道&#xff0c;支付宝可以给美区App Store 充钱&#xff0c;无需信用卡直接购买美区 Apple ID、Google Play、Spotify、Hulu礼品卡&#xff0c;下面就给大家介绍怎么购买 1.城市切换为&#xff1a;旧金山&#xff08;国际-> 北美洲…

p2p金融项目+支付宝充值

目录 前言 下载服务端SDK 时序图&#xff1a; 按照支付宝时序图的过程去做&#xff1a; 第一步&#xff1a; 第二步--2&#xff1a;生成充值记录&#xff08;状态&#xff1a;充值中&#xff09; 第四步&#xff1a;调支付宝的支付接口 第七八步&#xff1a;&#xff0…

RecyclerView实现仿支付宝充值界面

参考博客&#xff1a;https://www.jianshu.com/p/b4bb52cdbeb7 非常感谢上面这位博主的博客给了我非常好的灵感&#xff01;&#xff01;&#xff01; 下面我就先贴一下效果图&#xff1a; 布局代码&#xff1a; <?xml version"1.0" encoding"utf-8"…

JAVA端实现支付宝充值

2019独角兽企业重金招聘Python工程师标准>>> 前言&#xff1a;用户充值到平台 GitHub地址&#xff1a;https://github.com/wubiaowp/SpringCloud2.0.git 一、申请开发者账号-APPID、商户私钥、支付宝公钥、配置回调地址&#xff08;配置沙箱环境-测试&#xff09; 二…

discuz网站没备案无执照接入支付宝充值功能

discuz个人网站没备案无执照接入支付宝充值功能 文章目录 事情是这样的一、支付宝当面付是什么&#xff1f;二、如何申请当面付接口1.登录 支付宝商家中心2.点击“产品中心”&#xff0c;支付产品中选择当面付3.点击“立即开通”4.按步骤填写 三、创建应用及生成公钥和私钥1.登…

android约束布局充值页面,Android学习之RecylerView实习仿支付宝充值界面

今天周末&#xff0c;闲来无事&#xff0c;做了一个仿支付宝充值界面&#xff0c;主要知识点用RecylerView的GridlayoutManager布局管理器&#xff0c;实现不同数据类型&#xff0c;填充不同布局&#xff0c;功能包括单击选中&#xff0c;双击取消&#xff0c;支持可输入金额等…